More BitLocker improvements.
Ylian Saint-Hilaire committed
Feb 17, 2024 at 17:51 UTC
f2bc7d5349871f40ef70f75f7541336a91f1de05
4 files changed
+58
-80
agents/meshcore.js
+34
-37
@@ -654,22 +654,6 @@ var meshCoreObj = { action: 'coreinfo', value: (require('MeshAgent').coreHash ?
654
// Get the operating system description string
655
try { require('os').name().then(function (v) { meshCoreObj.osdesc = v; meshCoreObjChanged(); }); } catch (ex) { }
656
657
-// Get Volumes and BitLocker if Windows
658
-try {
659
- if (process.platform == 'win32') {
660
- if (require('computer-identifiers').volumes_promise != null) {
661
- var p = require('computer-identifiers').volumes_promise();
662
- p.then(function (res) {
663
- meshCoreObj.volumes = res;
664
- meshCoreObjChanged();
665
- });
666
- } else if (require('computer-identifiers').volumes != null) {
667
- meshCoreObj.volumes = require('computer-identifiers').volumes();
668
- meshCoreObjChanged();
669
- }
670
- }
671
-} catch(e) { }
672
-
657
// Setup logged in user monitoring (THIS IS BROKEN IN WIN7)
658
try {
659
var userSession = require('user-sessions');
@@ -1959,28 +1943,24 @@ function getSystemInformation(func) {
1943
results.hardware.network = { dns: require('os').dns() };
1944
replaceSpacesWithUnderscoresRec(results);
1945
var hasher = require('SHA384Stream').create();
1962
- // results.hash = hasher.syncHash(JSON.stringify(results)).toString('hex');
1963
- // func(results);
1946
1965
-
1947
// On Windows platforms, get volume information - Needs more testing.
1948
if (process.platform == 'win32')
1949
{
1950
results.pendingReboot = require('win-info').pendingReboot(); // Pending reboot
1970
-
1951
if (require('computer-identifiers').volumes_promise != null)
1952
{
1953
var p = require('computer-identifiers').volumes_promise();
1954
p.then(function (res)
1955
{
1976
- results.hardware.windows.volumes = res;
1956
+ results.hardware.windows.volumes = cleanGetBitLockerVolumeInfo(res);
1957
results.hash = hasher.syncHash(JSON.stringify(results)).toString('hex');
1958
func(results);
1959
});
1960
}
1961
else if (require('computer-identifiers').volumes != null)
1962
{
1983
- results.hardware.windows.volumes = require('computer-identifiers').volumes();
1963
+ results.hardware.windows.volumes = cleanGetBitLockerVolumeInfo(require('computer-identifiers').volumes());
1964
results.hash = hasher.syncHash(JSON.stringify(results)).toString('hex');
1965
func(results);
1966
}
@@ -3801,7 +3781,7 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
3781
if (require('os').dns != null) { availcommands += ',dnsinfo'; }
3782
try { require('linux-dhcp'); availcommands += ',dhcp'; } catch (ex) { }
3783
if (process.platform == 'win32') {
3804
- availcommands += ',cs,wpfhwacceleration,uac,volumes,rdpport';
3784
+ availcommands += ',bitlocker,cs,wpfhwacceleration,uac,volumes,rdpport';
3785
if (bcdOK()) { availcommands += ',safemode'; }
3786
if (require('notifybar-desktop').DefaultPinned != null) { availcommands += ',privacybar'; }
3787
try { require('win-utils'); availcommands += ',taskbar'; } catch (ex) { }
@@ -3962,6 +3942,17 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
3942
case 'volumes':
3943
response = JSON.stringify(require('win-volumes').getVolumes(), null, 1);
3944
break;
3945
+ case 'bitlocker':
3946
+ if (process.platform == 'win32') {
3947
+ if (require('computer-identifiers').volumes_promise != null) {
3948
+ var p = require('computer-identifiers').volumes_promise();
3949
+ p.then(function (res) { sendConsoleText(JSON.stringify(cleanGetBitLockerVolumeInfo(res), null, 1), this.session); });
3950
+ response = "Please wait...";
3951
+ } else if (require('computer-identifiers').volumes != null) {
3952
+ sendConsoleText(JSON.stringify(cleanGetBitLockerVolumeInfo(require('computer-identifiers').volumes()), null, 1), this.session);
3953
+ }
3954
+ }
3955
+ break;
3956
case 'dhcp': // This command is only supported on Linux, this is because Linux does not give us the DNS suffix for each network adapter independently so we have to ask the DHCP server.
3957
{
3958
try { require('linux-dhcp'); } catch (ex) { response = 'Unknown command "dhcp", type "help" for list of available commands.'; break; }
@@ -5702,6 +5693,7 @@ function sendPeriodicServerUpdate(flags, force) {
5693
});
5694
} catch (ex) { }
5695
}
5696
+
5697
// Get Defender for Windows Server
5698
try {
5699
var d = require('win-info').defender();
@@ -5709,20 +5701,7 @@ function sendPeriodicServerUpdate(flags, force) {
5701
meshCoreObj.defender = res;
5702
meshCoreObjChanged();
5703
});
5712
- } catch (ex){ }
5713
- // Get Volumes and BitLocker if Windows
5714
- try {
5715
- if (require('computer-identifiers').volumes_promise != null){
5716
- var p = require('computer-identifiers').volumes_promise();
5717
- p.then(function (res){
5718
- meshCoreObj.volumes = res;
5719
- meshCoreObjChanged();
5720
- });
5721
- }else if (require('computer-identifiers').volumes != null){
5722
- meshCoreObj.volumes = require('computer-identifiers').volumes();
5723
- meshCoreObjChanged();
5724
- }
5725
- } catch(e) { }
5704
+ } catch (ex) { }
5705
}
5706
5707
// Send available data right now
@@ -5736,6 +5715,24 @@ function sendPeriodicServerUpdate(flags, force) {
5715
}
5716
}
5717
5718
+// Sort the names in an object
5719
+function sortObject(obj) { return Object.keys(obj).sort().reduce(function(a, v) { a[v] = obj[v]; return a; }, {}); }
5720
+
5721
+// Fix the incoming data and cut down how much data we use
5722
+function cleanGetBitLockerVolumeInfo(volumes) {
5723
+ for (var i in volumes) {
5724
+ const v = volumes[i];
5725
+ if (typeof v.size == 'string') { v.size = parseInt(v.size); }
5726
+ if (v.identifier == '') { delete v.identifier; }
5727
+ if (v.name == '') { delete v.name; }
5728
+ if (v.removable != true) { delete v.removable; }
5729
+ if (v.protectionStatus == 'On') { v.protectionStatus = true; } else { delete v.protectionStatus; }
5730
+ if (v.volumeStatus == 'FullyDecrypted') { delete v.volumeStatus; }
5731
+ if (v.recoveryPassword == '') { delete v.recoveryPassword; }
5732
+ }
5733
+ return sortObject(volumes);
5734
+}
5735
+
5736
// Once we are done collecting all the data, send to server if needed
5737
var LastPeriodicServerUpdate = null;
5738
var PeriodicServerUpdateNagleTimer = null;
meshagent.js
+2
-15
@@ -1940,21 +1940,8 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
1940
// TODO: Check that the agent has an interface that is the same as the one we got this websocket connection on. Only set if we have a match.
1941
}
1942
1943
- // Volumes and BitLocker
1944
- if (command.volumes != null) {
1945
- for (var i in command.volumes) {
1946
- // Fix the incoming data and cut down how much data we use
1947
- const v = command.volumes[i];
1948
- if (typeof v.size == 'string') { v.size = parseInt(v.size); }
1949
- if (v.recoveryPassword == '') { delete v.recoveryPassword; }
1950
- if (v.identifier == '') { delete v.identifier; }
1951
- if (v.name == '') { delete v.name; }
1952
- if (v.removable != true) { delete v.removable; }
1953
- if (v.protectionStatus == 'On') { v.protectionStatus = true; } else { delete v.protectionStatus; }
1954
- if (v.volumeStatus == "FullyDecrypted") { delete v.volumeStatus; }
1955
- }
1956
- if (JSON.stringify(device.volumes) != JSON.stringify(command.volumes)) { device.volumes = command.volumes; change = 1; }
1957
- }
1943
+ // Remove old volumes and BitLocker data, this is part of sysinfo.
1944
+ delete device.volumes;
1945
1946
// If there are changes, event the new device
1947
if (change == 1) {
meshuser.js
+6
@@ -6273,6 +6273,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
6273
delete doc.type;
6274
delete doc.domain;
6275
delete doc._id;
6276
+
6277
+ // If this is not a device group admin users, don't send any BitLocker recovery passwords
6278
+ if ((rights != MESHRIGHT_ADMIN) && (doc.hardware) && (doc.hardware.windows) && (doc.hardware.windows.volumes)) {
6279
+ for (var i in doc.hardware.windows.volumes) { delete doc.hardware.windows.volumes[i].recoveryPassword; }
6280
+ }
6281
+
6282
if (command.nodeinfo === true) { doc.node = node; doc.rights = rights; }
6283
obj.send(doc);
6284
} else {
views/default.handlebars
+16
-28
@@ -7451,21 +7451,6 @@
7451
x += addDeviceAttribute("Antivirus", y.join('<br />'));
7452
}
7453
7454
- /*
7455
- // Volumes and Bitlocker
7456
- if (node.volumes){
7457
- var bitlocker = [];
7458
- for (var i in node.volumes) {
7459
- if (typeof node.volumes[i].protectionStatus !== 'undefined' && node.volumes[i].protectionStatus == 'On'){
7460
- bitlocker.push('<div style=margin-bottom:2px>' + addKeyLinkConditional(i + ' - <span style=color:green>' + EscapeHtml(node.volumes[i].volumeStatus) + '</span>', 'p10showBitlockerKey(\'' + i + '\')', (userinfo.siteadmin == 0xFFFFFFFF)) + '</div>');
7461
- } else if (typeof node.volumes[i].protectionStatus !== 'undefined') {
7462
- bitlocker.push('<div style=margin-bottom:2px>' + i + ' - <span style=color:red>' + EscapeHtml(node.volumes[i].volumeStatus) + '</span>' + '</div>');
7463
- }
7464
- }
7465
- if (bitlocker.length > 0) { x += addDeviceAttribute("BitLocker", bitlocker.join(' ')); }
7466
- }
7467
- */
7468
-
7454
// Active Users
7455
if (node.users && node.conn && (node.users.length > 0) && (node.conn & 1)) { x += addDeviceAttribute(((node.users.length > 1)?"Active Users":"Active User"), EscapeHtml(node.users.join(', '))); }
7456
@@ -7918,13 +7903,6 @@
7903
}
7904
}
7905
7921
- function p10showBitlockerKey(drive) {
7922
- if (xxdialogMode) return false;
7923
- var x = '<div><p>' + "Identifier" + '</p><p style=user-select:text;font-weight:bold>' + EscapeHtml(currentNode.volumes[drive].identifier ? currentNode.volumes[drive].identifier : "Unknown") + '</p>';
7924
- x += '<p>' + "Recovery Password" + '</p><p style=user-select:text;font-weight:bold>' + EscapeHtml(currentNode.volumes[drive].recoveryPassword ? currentNode.volumes[drive].recoveryPassword : "Unknown") + '</p></div>';
7925
- setDialogMode(2, EscapeHtml(drive) + ': ' + "BitLocker Information", 1, null, x, '');
7926
- }
7927
-
7906
function p20editDeviceNotify() {
7907
if (xxdialogMode) return false;
7908
var devNotify = 0, fx = ((features2 & 0x00004000) && (userinfo.emailVerified))?1:0;
@@ -12123,24 +12101,27 @@
12101
}
12102
12103
// Volumes and Bitlocker
12126
- if (node.volumes) {
12104
+ if (hardware.windows && hardware.windows.volumes) {
12105
var x = '';
12128
- for (var i in node.volumes) {
12129
- var m = node.volumes[i];
12106
+ for (var i in hardware.windows.volumes) {
12107
+ var m = hardware.windows.volumes[i];
12108
x += '<tr><td><div class=style10 style=border-radius:5px;padding:8px>';
12109
x += '<div style=margin-bottom:3px><b>' + i + ':' + (((m.name == null) || (m.name == '')) ? '' : (' - ' + EscapeHtml(m.name))) + '</b></div>';
12110
if (m.size) {
12111
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
12134
- var i = parseInt(Math.floor(Math.log(Math.abs(m.size)) / Math.log(1024)), 10);
12135
- var fsize = (i === 0 ? `${m.size} ${sizes[i]}` : `${(m.size / (1024 ** i)).toFixed(2)} ${sizes[i]}`);
12112
+ var j = parseInt(Math.floor(Math.log(Math.abs(m.size)) / Math.log(1024)), 10);
12113
+ var fsize = (j === 0 ? `${m.size} ${sizes[j]}` : `${(m.size / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
12114
x += addDetailItem("Capacity", EscapeHtml(fsize), s);
12115
}
12116
if (m.type) { x += addDetailItem("File System", (m.removable == true ? ("Removable" + ' / ') : '') + EscapeHtml(m.type), s); }
12117
+
12118
if (m.protectionStatus || m.volumeStatus) {
12119
var bitlockerState = [];
12120
if (m.protectionStatus) bitlockerState.push("Enabled");
12121
if (m.volumeStatus) bitlockerState.push(EscapeHtml(m.volumeStatus));
12143
- x += addDetailItem("BitLocker", bitlockerState.join(' - '), s);
12122
+ bitlockerState = bitlockerState.join(' - ');
12123
+ if (m.recoveryPassword) { bitlockerState += addKeyLink('', 'deviceDetailsShowBitlockerInfo(\"' + encodeURIComponentEx(i) + '\",\"' + encodeURIComponentEx(m.identifier) + '\",\"' + encodeURIComponentEx(m.recoveryPassword) + '\")'); }
12124
+ x += addDetailItem("BitLocker", bitlockerState, s);
12125
}
12126
x += '</div>';
12127
}
@@ -12167,6 +12148,13 @@
12148
}
12149
}
12150
12151
+ function deviceDetailsShowBitlockerInfo(drive, identifier, password) {
12152
+ if (xxdialogMode) return false;
12153
+ var x = '<div><p>' + "Identifier" + '</p><p style=user-select:text;font-weight:bold>' + (identifier ? decodeURIComponent(identifier) : "Unknown") + '</p>';
12154
+ x += '<p>' + "Recovery Password" + '</p><p style=user-select:text;font-weight:bold>' + (password ? decodeURIComponent(password) : "Unknown") + '</p></div>';
12155
+ setDialogMode(2, decodeURIComponent(drive) + ': ' + "BitLocker Information", 1, null, x, '');
12156
+ }
12157
+
12158
//
12159
// CONSOLE
12160
//