mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-09-11 08:55:32 +03:00
Merge branch 'master' of https://github.com/Ylianst/MeshCentral
This commit is contained in:
commit
c937764980
49
SECURITY.md
Normal file
49
SECURITY.md
Normal file
@ -0,0 +1,49 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Any version of MeshCentral 1.x.x is supported.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 1.x.x | :white_check_mark: |
|
||||
| < 1.0 | :x: |
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
Please report any concerns or security issue to Ylian Saint-Hilaire (ylianst@gmail.com). If needed, use my PGP key below.
|
||||
|
||||
```
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
Version: BCPG v1.56
|
||||
|
||||
mQMuBF2gC4sRCAClFNvMCCVW3ego3UHBQ6LhSenJfaZYhvn8gaGuemSQxqTI6bla
|
||||
BTAv3aMtQnvqlSuadMMegb+FO6hnaQMlGvpVA1qpkSzgrPS5HrBD3H33J2Nj3i93
|
||||
ZpDPpxdI0ehCj6IJPnl0GxGbpKIN8YpJUFl44wv1lMRFI1lgyb+dCoO60irYdNQB
|
||||
PV85BI+DwPfOBFHunwR78nqMvpvsk9HaeHjEP7oXr952/7EazUowZsMlEfkYnw5S
|
||||
+tLfpCoY3QWkektpJP40nMJSKQdV2NEuED99doA0X+7P1vsvFFFyMH69dnU2uSay
|
||||
XCHpkAbntBy0BGmtF1RnTcOMv2V/LPXnlMdvAQCbmLQzNra3r163tcdRY0jSs+pZ
|
||||
1L3w5tHNj2dzhfpa7wf/SIuds6QTr2LCN6miLoSVCRMMpT7d771b16GwQqWEXzN2
|
||||
+h7dYqrssHPOa8FSUrPerz0+0eFcbMSm5/L/4KXWXoQthURv8aMP9E0iVoUYaaKB
|
||||
7U+5vFEZbpoOZyZmTAjXQMSNZCft0azA82Q+G85euyicWtMv48yNVzUhkdh+M2ud
|
||||
ohkXX2Aor1TqpBJoIeWke7j9D+Bo+lu61zPRx5ed9teUeLJCwqNEjlE+6gre5kxF
|
||||
PoreAtn59QYcBIpzQEWVMbNFlDAR4jMyqIoKCGfBPiRw2V+kunbzqiGQEglIFfOt
|
||||
6sTN/+CJh0ei976VDmE0Z1kMN+CNLgIjIw8fl02V9QgAnHcpqtVUxR4dbGOhVDq5
|
||||
lWv+K75QQlWyXC2k+KboXcaCvH0WZEBACYzO0CfrZ5hP9BSkbj5usSUVGGHwEFAJ
|
||||
t+/04KVY71fW281Ej5kGNaIKxeKsx6+hMo+UXb5ZM+6fANNNxs1cK95sTH6PjkyB
|
||||
tsKxLoa3CV2v9mSE5JiKKt74R9nXVo7PXf6DizwAU2l30Lb6y6y0OdXdCCPAG8Ij
|
||||
FrMgPu5MtjgsO5DnkZfUqDPWHhOgEPyOh3Ho+pvDhNYh5cm2eLQ8g5orzs2FHwbZ
|
||||
DpAHwCdqrlcpBlKJ4W/MZdf1fg2PjqaTWm7ZFiGr91P0F6kltTLWbVKTjLdS0T+D
|
||||
L7QnWWxpYW4gU2FpbnQtSGlsYWlyZSA8eWxpYW5zdEBnbWFpbC5jb20+iF4EExEI
|
||||
AAYFAl2gC4sACgkQg7j/r4DH+kD/3gD+MRedlM53VzOtNOpS6mqDAxj1aWP90HN0
|
||||
AqO6zuCTyGgBAJlunLFKH8IUetmQOhiohB8HVhdm/q4lKRDV7sHdplDyuMwEXaAL
|
||||
ixACAJSU/sCV87he4oZUKzg2/IGl3QoDSbTCOd04dE1IjPjjHbi8t9M7Qau55aM8
|
||||
ypFEsc7zMslL8Fc78EejrKmM3zsB/RU9XWFyrbQwRbaK6OHeEHC2E3AFaG0p09c6
|
||||
d0kZloHuWyEsm5a/3PpbIM1eP9IESJXWCc+bQQt6DxLKHLmkKMwB/icWMg8uMJlx
|
||||
aady8TEq7LH5oFVKsglnwuN1nIkecrf77TVkEqTjIxS6TiOup6zOnioFNKLYBAH0
|
||||
WUnJEYFvx4OIXgQYEQgABgUCXaALiwAKCRCDuP+vgMf6QGFTAQCUj2gGwsFlN0eR
|
||||
Wowv4eLcc3FwQ+lBElUctKg8vNFb0gD/ZWVWsWwKerNgNnf7RGD9mt8G2CKvdgGG
|
||||
oZ2hPP2gU9w=
|
||||
=roW4
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
```
|
Binary file not shown.
@ -3438,6 +3438,24 @@ function onTunnelData(data)
|
||||
this.zip.on('progress', require('events').moderated(function (name, p) { this.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: 'zippingFile', file: ((process.platform == 'win32') ? (name.split('/').join('\\')) : name), progress: p }))); }, 1000));
|
||||
this.zip.pipe(out);
|
||||
break;
|
||||
case 'unzip':
|
||||
if (this.unzip != null) return; // Unzip operating is currently running, exit now.
|
||||
this.unzip = require('zip-reader').read(cmd.input);
|
||||
this.unzip._dest = cmd.dest;
|
||||
this.unzip.xws = this;
|
||||
this.unzip.then(function (zipped) {
|
||||
this.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: 'unzipping' })));
|
||||
zipped.xws = this.xws;
|
||||
zipped.extractAll(this._dest).then(function () { // finished extracting
|
||||
zipped.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: null })));
|
||||
zipped.xws.write(Buffer.from(JSON.stringify({ action: 'refresh' })));
|
||||
delete zipped.xws.unzip;
|
||||
}, function (e) { // error extracting
|
||||
zipped.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: 'unziperror', error: e })));
|
||||
delete zipped.xws.unzip;
|
||||
});
|
||||
}, function (e) { this.xws.write(Buffer.from(JSON.stringify({ action: 'dialogmessage', msg: 'unziperror', error: e }))); delete this.xws.unzip });
|
||||
break;
|
||||
case 'cancel':
|
||||
// Cancel zip operation if present
|
||||
try { this.zipcancel = true; this.zip.cancel(function () { }); } catch (ex) { }
|
||||
@ -4247,12 +4265,12 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
|
||||
break;
|
||||
case 'unzip':
|
||||
if (args['_'].length == 0) {
|
||||
response = "Proper usage: unzip input, destination"; // Display usage
|
||||
response = "Proper usage: unzip input,destination"; // Display usage
|
||||
} else {
|
||||
var p = args['_'].join(' ').split(',');
|
||||
if (p.length != 2) { response = "Proper usage: unzip input, destination"; break; } // Display usage
|
||||
var prom = require('zip-reader').read(p[0]);
|
||||
prom._dest = p[1];
|
||||
if (p.length != 2) { response = "Proper usage: unzip input,destination"; break; } // Display usage
|
||||
var prom = require('zip-reader').read(p[0].trim());
|
||||
prom._dest = p[1].trim();
|
||||
prom.self = this;
|
||||
prom.sessionid = sessionid;
|
||||
prom.then(function (zipped) {
|
||||
@ -4733,8 +4751,11 @@ function processConsoleCommand(cmd, args, rights, sessionid) {
|
||||
}
|
||||
case 'sysinfo': { // Return system information
|
||||
getSystemInformation(function (results, err) {
|
||||
if (results == null) { sendConsoleText(err, this.sessionid); } else {
|
||||
if (results == null) {
|
||||
sendConsoleText(err, this.sessionid);
|
||||
} else {
|
||||
sendConsoleText(JSON.stringify(results, null, 1), this.sessionid);
|
||||
mesh.SendCommand({ action: 'sysinfo', sessionid: this.sessionid, data: results });
|
||||
}
|
||||
});
|
||||
break;
|
||||
@ -5723,9 +5744,11 @@ function cleanGetBitLockerVolumeInfo(volumes) {
|
||||
for (var i in volumes) {
|
||||
const v = volumes[i];
|
||||
if (typeof v.size == 'string') { v.size = parseInt(v.size); }
|
||||
if (typeof v.sizeremaining == 'string') { v.sizeremaining = parseInt(v.sizeremaining); }
|
||||
if (v.identifier == '') { delete v.identifier; }
|
||||
if (v.name == '') { delete v.name; }
|
||||
if (v.removable != true) { delete v.removable; }
|
||||
if (v.cdrom != true) { delete v.cdrom; }
|
||||
if (v.protectionStatus == 'On') { v.protectionStatus = true; } else { delete v.protectionStatus; }
|
||||
if (v.volumeStatus == 'FullyDecrypted') { delete v.volumeStatus; }
|
||||
if (v.recoveryPassword == '') { delete v.recoveryPassword; }
|
||||
|
@ -390,7 +390,7 @@ function windows_volumes()
|
||||
p1.child = child;
|
||||
child.promise = p1;
|
||||
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||
child.stdin.write('Get-Volume | Select-Object -Property DriveLetter,FileSystemLabel,FileSystemType,Size,DriveType | ConvertTo-Csv -NoTypeInformation\nexit\n');
|
||||
child.stdin.write('Get-Volume | Select-Object -Property DriveLetter,FileSystemLabel,FileSystemType,Size,SizeRemaining,DriveType | ConvertTo-Csv -NoTypeInformation\nexit\n');
|
||||
child.on('exit', function (c)
|
||||
{
|
||||
var a, i, tokens, key;
|
||||
@ -407,7 +407,9 @@ function windows_volumes()
|
||||
name: tokens[1].split('"')[1],
|
||||
type: tokens[2].split('"')[1],
|
||||
size: tokens[3].split('"')[1],
|
||||
removable: tokens[4].split('"')[1] == 'Removable'
|
||||
sizeremaining: tokens[4].split('"')[1],
|
||||
removable: tokens[5].split('"')[1] == 'Removable',
|
||||
cdrom: tokens[5].split('"')[1] == 'CD-ROM'
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -447,12 +449,14 @@ function windows_volumes()
|
||||
var abc = lines[x].trim();
|
||||
var englishidpass = (abc !== '' && abc.includes('Numerical Password:')); // English ID
|
||||
var germanidpass = (abc !== '' && abc.includes('Numerisches Kennwort:')); // German ID
|
||||
var frenchidpass = (abc !== '' && abc.includes('Mot de passe num')); // French ID
|
||||
var englishpass = (abc !== '' && abc.includes('Password:') && !abc.includes('Numerical Password:')); // English Password
|
||||
var germanpass = (abc !== '' && abc.includes('Kennwort:') && !abc.includes('Numerisches Kennwort:')); // German Password
|
||||
if (englishidpass || germanidpass || englishpass || germanpass) {
|
||||
var frenchpass = (abc !== '' && abc.includes('Mot de passe :') && !abc.includes('Mot de passe num')); // French Password
|
||||
if (englishidpass || germanidpass || frenchidpass|| englishpass || germanpass || frenchpass) {
|
||||
var nextline = lines[x + 1].trim();
|
||||
if (x + 1 < lines.length && (nextline !== '' && nextline.startsWith('ID:'))) {
|
||||
identifier = nextline.replace('ID:','').trim();
|
||||
if (x + 1 < lines.length && (nextline !== '' && (nextline.startsWith('ID:') || nextline.startsWith('ID :')) )) {
|
||||
identifier = nextline.replace('ID:','').replace('ID :', '').trim();
|
||||
foundIDMarkedLine = true;
|
||||
}else if (x + 1 < lines.length && nextline !== '') {
|
||||
password = nextline;
|
||||
@ -559,7 +563,7 @@ function windows_identifiers()
|
||||
}
|
||||
function macos_identifiers()
|
||||
{
|
||||
var ret = { identifiers: {} };
|
||||
var ret = { identifiers: {}, darwin: {} };
|
||||
var child;
|
||||
|
||||
child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
@ -598,6 +602,84 @@ function macos_identifiers()
|
||||
child.waitExit();
|
||||
ret.identifiers.cpu_name = child.stdout.str.trim();
|
||||
|
||||
child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||
child.stdin.write('system_profiler SPMemoryDataType\nexit\n');
|
||||
child.waitExit();
|
||||
var lines = child.stdout.str.trim().split('\n');
|
||||
if(lines.length > 0) {
|
||||
const memorySlots = [];
|
||||
if(lines[2].trim().includes('Memory Slots:')) { // OLD MACS WITH SLOTS
|
||||
const Memory = [];
|
||||
const bankMatches = child.stdout.str.trim().match(/BANK \d+\/DIMM\d+:[\s\S]*?(?=(BANK|$))/g);
|
||||
bankMatches.forEach(function(match, index) {
|
||||
const bankInfo = match.match(/BANK (\d+)\/DIMM(\d+):[\s\S]*?Size: (\d+ \w+)[\s\S]*?Type: (\w+)[\s\S]*?Speed: (\d+ \w+)[\s\S]*?Status: (\w+)[\s\S]*?Manufacturer: (0x[0-9A-Fa-f]+)[\s\S]*?Part Number: (0x[0-9A-Fa-f]+)[\s\S]*?Serial Number: (.+)/);
|
||||
if (bankInfo) {
|
||||
const bankIndex = bankInfo[1].trim();
|
||||
const dimmIndex = bankInfo[2].trim();
|
||||
const size = bankInfo[3].trim();
|
||||
const type = bankInfo[4].trim();
|
||||
const speed = bankInfo[5].trim();
|
||||
const status = bankInfo[6].trim();
|
||||
const manufacturer = bankInfo[7].trim();
|
||||
const partNumber = bankInfo[8].trim();
|
||||
const serialNumber = bankInfo[9].trim();
|
||||
Memory.push({
|
||||
DeviceLocator: "BANK " + bankIndex + "/DIMM" + dimmIndex,
|
||||
Size: size,
|
||||
Type: type,
|
||||
Speed: speed,
|
||||
Status: status,
|
||||
Manufacturer: hexToAscii(manufacturer),
|
||||
PartNumber: hexToAscii(partNumber),
|
||||
SerialNumber: serialNumber,
|
||||
});
|
||||
}
|
||||
});
|
||||
memorySlots = Memory;
|
||||
} else { // NEW MACS WITHOUT SLOTS
|
||||
memorySlots.push({ DeviceLocator: "Onboard Memory", Size: lines[2].split(":")[1].trim(), PartNumber: lines[3].split(":")[1].trim(), Manufacturer: lines[4].split(":")[1].trim() })
|
||||
}
|
||||
ret.darwin.memory = memorySlots;
|
||||
}
|
||||
|
||||
child = require('child_process').execFile('/bin/sh', ['sh']);
|
||||
child.stdout.str = ''; child.stdout.on('data', function (c) { this.str += c.toString(); });
|
||||
child.stdin.write('diskutil info -all\nexit\n');
|
||||
child.waitExit();
|
||||
var sections = child.stdout.str.split('**********\n');
|
||||
if(sections.length > 0){
|
||||
var devices = [];
|
||||
for (var i = 0; i < sections.length; i++) {
|
||||
var lines = sections[i].split('\n');
|
||||
var deviceInfo = {};
|
||||
var wholeYes = false;
|
||||
var physicalYes = false;
|
||||
var oldmac = false;
|
||||
for (var j = 0; j < lines.length; j++) {
|
||||
var keyValue = lines[j].split(':');
|
||||
var key = keyValue[0].trim();
|
||||
var value = keyValue[1] ? keyValue[1].trim() : '';
|
||||
if (key === 'Virtual') oldmac = true;
|
||||
if (key === 'Whole' && value === 'Yes') wholeYes = true;
|
||||
if (key === 'Virtual' && value === 'No') physicalYes = true;
|
||||
if(value && key === 'Device / Media Name'){
|
||||
deviceInfo['Caption'] = value;
|
||||
}
|
||||
if(value && key === 'Disk Size'){
|
||||
deviceInfo['Size'] = value.split(' ')[0] + ' ' + value.split(' ')[1];
|
||||
}
|
||||
}
|
||||
if (wholeYes) {
|
||||
if (oldmac) {
|
||||
if (physicalYes) devices.push(deviceInfo);
|
||||
} else {
|
||||
devices.push(deviceInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret.identifiers.storage_devices = devices;
|
||||
}
|
||||
|
||||
trimIdentifiers(ret.identifiers);
|
||||
|
||||
@ -606,6 +688,17 @@ function macos_identifiers()
|
||||
return (ret);
|
||||
}
|
||||
|
||||
function hexToAscii(hexString) {
|
||||
hexString = hexString.startsWith('0x') ? hexString.slice(2) : hexString;
|
||||
var str = '';
|
||||
for (var i = 0; i < hexString.length; i += 2) {
|
||||
var hexPair = hexString.substr(i, 2);
|
||||
str += String.fromCharCode(parseInt(hexPair, 16));
|
||||
}
|
||||
str = str.replace(/[\u007F-\uFFFF]/g, ''); // Remove characters from 0x0080 to 0xFFFF
|
||||
return str.trim();
|
||||
}
|
||||
|
||||
function win_chassisType()
|
||||
{
|
||||
var child = require('child_process').execFile(process.env['windir'] + '\\System32\\wbem\\wmic.exe', ['wmic', 'SystemEnclosure', 'get', 'ChassisTypes']);
|
||||
|
29
meshctrl.js
29
meshctrl.js
@ -879,6 +879,7 @@ if (args['_'].length == 0) {
|
||||
console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --start " + localISOTime + " --duration 30"));
|
||||
console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --start " + localISOTime + " --duration 30 --daily"));
|
||||
console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --type desktop,terminal --consent prompt"));
|
||||
console.log(winRemoveSingleQuotes(" MeshCtrl DeviceSharing --id 'deviceid' --add Guest --type http --port 80"));
|
||||
console.log("\r\nRequired arguments:\r\n");
|
||||
if (process.platform == 'win32') {
|
||||
console.log(" --id [deviceid] - The device identifier.");
|
||||
@ -888,14 +889,15 @@ if (args['_'].length == 0) {
|
||||
console.log("\r\nOptional arguments:\r\n");
|
||||
console.log(" --remove [shareid] - Remove a device sharing link.");
|
||||
console.log(" --add [guestname] - Add a device sharing link.");
|
||||
console.log(" --type [desktop,terminal,files] - Type of sharing to add, can be combined. default is desktop.");
|
||||
console.log(" --type [desktop,terminal,files,http,https] - Type of sharing to add, can be combined. default is desktop.");
|
||||
console.log(" --viewonly - Make desktop sharing view only.");
|
||||
console.log(" --consent [notify,prompt] - Consent flags, default is notify.");
|
||||
console.log(" --consent [notify,prompt,none] - Consent flags, default is notify.");
|
||||
console.log(" --start [yyyy-mm-ddThh:mm:ss] - Start time, default is now.");
|
||||
console.log(" --end [yyyy-mm-ddThh:mm:ss] - End time.");
|
||||
console.log(" --duration [minutes] - Duration of the share, default is 60 minutes.");
|
||||
console.log(" --daily - Add recurring daily device share.");
|
||||
console.log(" --weekly - Add recurring weekly device share.");
|
||||
console.log(" --port [portnumber] - Set alternative port for http or https, default is 80 for http and 443 for https.");
|
||||
break;
|
||||
}
|
||||
case 'agentdownload': {
|
||||
@ -1707,10 +1709,12 @@ function serverConnect() {
|
||||
var p = 0;
|
||||
if (args.type != null) {
|
||||
var shareTypes = args.type.toLowerCase().split(',');
|
||||
for (var i in shareTypes) { if ((shareTypes[i] != 'terminal') && (shareTypes[i] != 'desktop') && (shareTypes[i] != 'files')) { console.log("Unknown sharing type: " + shareTypes[i]); process.exit(1); } }
|
||||
for (var i in shareTypes) { if ((shareTypes[i] != 'terminal') && (shareTypes[i] != 'desktop') && (shareTypes[i] != 'files') && (shareTypes[i] != 'http') && (shareTypes[i] != 'https')) { console.log("Unknown sharing type: " + shareTypes[i]); process.exit(1); } }
|
||||
if (shareTypes.indexOf('terminal') >= 0) { p |= 1; }
|
||||
if (shareTypes.indexOf('desktop') >= 0) { p |= 2; }
|
||||
if (shareTypes.indexOf('files') >= 0) { p |= 4; }
|
||||
if (shareTypes.indexOf('http') >= 0) { p |= 8; }
|
||||
if (shareTypes.indexOf('https') >= 0) { p |= 16; }
|
||||
}
|
||||
if (p == 0) { p = 2; } // Desktop
|
||||
|
||||
@ -1745,6 +1749,19 @@ function serverConnect() {
|
||||
}
|
||||
}
|
||||
|
||||
var port = null;
|
||||
// Set Port Number if http or https
|
||||
if ((p & 8) || (p & 16)) {
|
||||
if (typeof args.port == 'number') {
|
||||
if ((args.port < 1) || (args.port > 65535)) { console.log("Port number must be between 1 and 65535."); process.exit(1); }
|
||||
port = args.port;
|
||||
} else if ((p & 8)) {
|
||||
port = 80;
|
||||
} else if ((p & 16)) {
|
||||
port = 443;
|
||||
}
|
||||
}
|
||||
|
||||
// Start and end time
|
||||
var start = null, end = null;
|
||||
if (args.start) { start = Math.floor(Date.parse(args.start) / 1000); end = start + (60 * 60); }
|
||||
@ -1761,14 +1778,14 @@ function serverConnect() {
|
||||
if ((typeof args.duration != 'number') || (args.duration < 1)) { console.log("Invalid duration value."); process.exit(1); return; }
|
||||
|
||||
// Recurring sharing
|
||||
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, start: start, expire: args.duration, recurring: recurring, viewOnly: viewOnly, responseid: 'meshctrl' }));
|
||||
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, start: start, expire: args.duration, recurring: recurring, viewOnly: viewOnly, port: port, responseid: 'meshctrl' }));
|
||||
} else {
|
||||
if ((start == null) && (end == null)) {
|
||||
// Unlimited sharing
|
||||
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, expire: 0, viewOnly: viewOnly, responseid: 'meshctrl' }));
|
||||
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, expire: 0, viewOnly: viewOnly, port: port, responseid: 'meshctrl' }));
|
||||
} else {
|
||||
// Time limited sharing
|
||||
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, start: start, end: end, viewOnly: viewOnly, responseid: 'meshctrl' }));
|
||||
ws.send(JSON.stringify({ action: 'createDeviceShareLink', nodeid: args.id, guestname: args.add, p: p, consent: consent, start: start, end: end, viewOnly: viewOnly, port: port, responseid: 'meshctrl' }));
|
||||
}
|
||||
}
|
||||
} else if (args.remove) {
|
||||
|
@ -4304,7 +4304,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
|
||||
// If we have view only remote desktop rights, force view-only on the guest share.
|
||||
if ((rights != MESHRIGHT_ADMIN) && ((rights & MESHRIGHT_REMOTEVIEWONLY) != 0)) { command.viewOnly = true; command.p = (command.p & 1); }
|
||||
if ((rights != MESHRIGHT_ADMIN) && ((rights & MESHRIGHT_REMOTEVIEWONLY) != 0)) { command.viewOnly = true; }
|
||||
|
||||
// Create cookie
|
||||
var publicid = getRandomPassword(), startTime = null, expireTime = null, duration = null;
|
||||
|
4
package-lock.json
generated
4
package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "meshcentral",
|
||||
"version": "1.1.20",
|
||||
"version": "1.1.21",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "meshcentral",
|
||||
"version": "1.1.20",
|
||||
"version": "1.1.21",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@yetzt/nedb": "1.8.0",
|
||||
|
@ -1311,6 +1311,10 @@ NoMeshesPanel img {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
#d2netinfo .dialogText {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#p12warning, #p12warning2, #p11warning, #p11warning2 {
|
||||
max-width: 100%;
|
||||
display: none;
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
//const zlib = require('zlib');
|
||||
var performCheck = false;
|
||||
var translationTable = null;
|
||||
@ -563,13 +564,13 @@ function totext(source, target, lang) {
|
||||
|
||||
if (splitOutputPtr == 1) {
|
||||
// Save the target back
|
||||
fs.writeFileSync(target + '-' + lang + '.txt', output.join('\r\n'), { flag: 'w+' });
|
||||
fs.writeFileSync(target + '-' + lang + '.txt', output.join(os.EOL), { flag: 'w+' });
|
||||
log('Done.');
|
||||
} else {
|
||||
// Save the text in 1000 string bunches
|
||||
for (var i in splitOutput) {
|
||||
log('Writing ' + target + '-' + lang + '-' + i + '.txt...');
|
||||
fs.writeFileSync(target + '-' + lang + '-' + i + '.txt', splitOutput[i].join('\r\n'), { flag: 'w+' });
|
||||
fs.writeFileSync(target + '-' + lang + '-' + i + '.txt', splitOutput[i].join(os.EOL), { flag: 'w+' });
|
||||
}
|
||||
log('Done.');
|
||||
}
|
||||
@ -585,7 +586,7 @@ function fromtext(source, target, lang) {
|
||||
|
||||
// Read raw text
|
||||
var rawText = fs.readFileSync(target).toString('utf8');
|
||||
var rawTextArray = rawText.split('\r\n');
|
||||
var rawTextArray = rawText.split(/\r?\n/);
|
||||
var rawTextPtr = 0;
|
||||
|
||||
log('Translation file: ' + sourceLangFileData.strings.length + ' string(s)');
|
||||
@ -733,7 +734,7 @@ function extract(langFile, sources) {
|
||||
|
||||
function extractFromTxt(file) {
|
||||
log("Processing TXT: " + path.basename(file));
|
||||
var lines = fs.readFileSync(file).toString().split('\r\n');
|
||||
var lines = fs.readFileSync(file).toString().split(/\r?\n/);
|
||||
var name = path.basename(file);
|
||||
for (var i in lines) {
|
||||
var line = lines[i];
|
||||
@ -847,7 +848,7 @@ function getStringFromJavaScript(name, script) {
|
||||
|
||||
function translateFromTxt(lang, file, createSubDir) {
|
||||
log("Translating TXT (" + lang + "): " + path.basename(file));
|
||||
var lines = fs.readFileSync(file).toString().split('\r\n'), outlines = [];
|
||||
var lines = fs.readFileSync(file).toString().split(/\r?\n/), outlines = [];
|
||||
for (var i in lines) {
|
||||
var line = lines[i];
|
||||
if ((line.length > 1) && (line[0] != '~')) {
|
||||
@ -857,7 +858,7 @@ function translateFromTxt(lang, file, createSubDir) {
|
||||
}
|
||||
}
|
||||
|
||||
var outname = file, out = outlines.join('\r\n');
|
||||
var outname = file, out = outlines.join(os.EOL);
|
||||
if (createSubDir != null) {
|
||||
var outfolder = path.join(path.dirname(file), createSubDir);
|
||||
if (fs.existsSync(outfolder) == false) { fs.mkdirSync(outfolder); }
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -81,8 +81,8 @@
|
||||
<div class="tab">
|
||||
<button id="twintab64" class="tablinks" onclick="openTab(event, 'wintab64')">Windows 64bit</button>
|
||||
<button id="twintab32" class="tablinks" onclick="openTab(event, 'wintab32')">Windows 32bit</button>
|
||||
<button id="tlinuxtab" class="tablinks" onclick="openTab(event, 'linuxtab')">Linux</button>
|
||||
<button id="tlinuxbinarytab" class="tablinks" onclick="openTab(event, 'linuxbinarytab')">Linux Binary</button>
|
||||
<button id="tlinuxtab" class="tablinks" onclick="openTab(event, 'linuxtab')">Linux / BSD Scripts</button>
|
||||
<button id="tlinuxbinarytab" class="tablinks" onclick="openTab(event, 'linuxbinarytab')">Linux / BSD / macOS Binary</button>
|
||||
<button id="tmacostab" class="tablinks" onclick="openTab(event, 'macostab')">MacOS</button>
|
||||
<button id="tandrotab" class="tablinks" onclick="openTab(event, 'androtab')">Android</button>
|
||||
<button id="tassistab" class="tablinks" onclick="openTab(event, 'assistab')">Assistant</button>
|
||||
@ -253,7 +253,7 @@
|
||||
}
|
||||
|
||||
function linuxBinarySetup() {
|
||||
var x = '<h3>Linux Binary</h3>', moreoptions = '';
|
||||
var x = '<h3>' + "Linux / BSD / macOS Binary Installer" + '</h3>', moreoptions = '';
|
||||
var opts = '<select id=aginsSelect onchange=addAgentToMeshClick() style=width:236px>';
|
||||
opts += '<option value=5 selected>' + "Linux / BSD / macOS Binary Installer" + '</option>';
|
||||
opts += '</select>';
|
||||
@ -261,8 +261,8 @@
|
||||
var servername = window.location.hostname;
|
||||
if ((servername.indexOf('.') == -1)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name.
|
||||
var portStr = (serverPort == 443) ? '' : (':' + serverPort);
|
||||
var binaryInstallAgentsOrder = [ 6, 5, 10005, 25, 26, 28, 30, 32, 36, 37, 40, 41 ];
|
||||
var binaryInstallAgents = { 5 : 'Linux x86-32', 6 : 'Linux x86-64', 10005 : 'Apple OSX Universal', 25 : 'Linux ARM-HF, Rasberry Pi', 26 : 'Linux ARM64-HF', 28: 'Linux MIPS24KC (OpenWRT)', 30 : 'FreeBSD x86-64', 32: 'Linux ARM 64 bit (glibc/2.24 NOKVM)', 36: 'OpenWRT x86-64', 37: 'OpenBSD x86-64', 40: 'Linux MIPSEL24KC (OpenWRT)', 41: 'ARMADA/CORTEX-A53/MUSL (OpenWRT)' };
|
||||
var binaryInstallAgentsOrder = [ 6, 5, 10005, 25, 26, 28, 30, 32, 36, 37, 40, 41, 16, 29 ];
|
||||
var binaryInstallAgents = { 6 : 'Linux x86-64', 5 : 'Linux x86-32', 10005 : 'Apple OSX Universal', 25 : 'Linux ARM-HF, Rasberry Pi', 26 : 'Linux ARM64-HF', 28: 'Linux MIPS24KC (OpenWRT)', 30 : 'FreeBSD x86-64', 32: 'Linux ARM 64 bit (glibc/2.24 NOKVM)', 36: 'OpenWRT x86-64', 37: 'OpenBSD x86-64', 40: 'Linux MIPSEL24KC (OpenWRT)', 41: 'ARMADA/CORTEX-A53/MUSL (OpenWRT)', 16: 'Apple macOS x86-64', 29: 'Apple macOS ARM-64' };
|
||||
for (var i in binaryInstallAgentsOrder) { moreoptions += '<option value=' + binaryInstallAgentsOrder[i] + '>' + binaryInstallAgents[binaryInstallAgentsOrder[i]] + '</option>' }
|
||||
x += '<div id=aginsSysTypeDiv>';
|
||||
x += addHtmlValue("System Type", '<select id=aginsSysType onchange=addAgentToMeshClick() style=width:236px>' + moreoptions + '</select>');
|
||||
|
@ -5917,21 +5917,6 @@
|
||||
x += addDetailItem("Antivirus", y.join('<br />'));
|
||||
}
|
||||
|
||||
// Volumes and Bitlocker
|
||||
if (node.volumes){
|
||||
var bitlocker = [];
|
||||
for (var i in node.volumes) {
|
||||
if (typeof node.volumes[i].protectionStatus !== 'undefined' && node.volumes[i].protectionStatus == 'On'){
|
||||
bitlocker.push(i + ' - <span style=color:green>' + node.volumes[i].volumeStatus + '</span>');
|
||||
}else if (typeof node.volumes[i].protectionStatus !== 'undefined'){
|
||||
bitlocker.push(i + ' - <span style=color:red>' + node.volumes[i].volumeStatus + '</span>');
|
||||
}
|
||||
}
|
||||
if(bitlocker.length > 0){
|
||||
x += addDetailItem("BitLocker", bitlocker.join('<br />'));
|
||||
}
|
||||
}
|
||||
|
||||
if (x != '') { sections.push({ name: "Operating System", html: x, img: 'software' }); }
|
||||
}
|
||||
|
||||
@ -6073,9 +6058,9 @@
|
||||
if (tpm.SpecVersion) { x += addDetailItem("SpecVersion", parseFloat(EscapeHtml(tpm.SpecVersion)).toFixed(1), s); }
|
||||
if (tpm.ManufacturerId) { x += addDetailItem("ManufacturerId", EscapeHtml(tpm.ManufacturerId), s); }
|
||||
if (tpm.ManufacturerVersion) { x += addDetailItem("ManufacturerVersion", EscapeHtml(tpm.ManufacturerVersion), s); }
|
||||
if (tpm.IsActivated != null) { x += addDetailItem("IsActivated", EscapeHtml(tpm.IsActivated), s); }
|
||||
if (tpm.IsEnabled != null) { x += addDetailItem("IsEnabled", EscapeHtml(tpm.IsEnabled), s); }
|
||||
if (tpm.IsOwned != null) { x += addDetailItem("IsOwned", EscapeHtml(tpm.IsOwned), s); }
|
||||
if (tpm.IsActivated != null) { x += addDetailItem("IsActivated", (tpm.IsActivated ? "Yes" : "No"), s); }
|
||||
if (tpm.IsEnabled != null) { x += addDetailItem("IsEnabled", (tpm.IsEnabled ? "Yes" : "No"), s); }
|
||||
if (tpm.IsOwned != null) { x += addDetailItem("IsOwned", (tpm.IsOwned ? "Yes" : "No"), s); }
|
||||
if (x != '') { sections.push({ name: "TPM", html: x, img: 'tpm'}); }
|
||||
}
|
||||
|
||||
@ -6124,6 +6109,26 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (hardware.darwin) {
|
||||
if (hardware.darwin.memory && (hardware.darwin.memory.length > 0)) {
|
||||
var x = '';
|
||||
x += '<table style=width:100%>';
|
||||
for (var i in hardware.darwin.memory) {
|
||||
var m = hardware.darwin.memory[i];
|
||||
if(m.Size && (m.Size == 'No Module Installed')) continue;
|
||||
x += '<tr><td><div class=style10 style=border-radius:5px;padding:8px>';
|
||||
x += '<div style=margin-bottom:3px><b>' + EscapeHtml((m.DeviceLocator ? m.DeviceLocator : 'Unknown')) + '</b></div>';
|
||||
if (m.Size && m.Speed) { x += addDetailItem("Capacity / Speed", format("{0}, {1}", m.Size, m.Speed), s); }
|
||||
else if (m.Size) { x += addDetailItem("Capacity", format("{0}", (m.Size)), s); }
|
||||
console.log(m.Manufacturer);
|
||||
if (m.PartNumber) { x += addDetailItem("Part Number", EscapeHtml((m.Manufacturer && m.Manufacturer != '')?(m.Manufacturer + ', '):'') + EscapeHtml(m.PartNumber), s); }
|
||||
x += '</div>';
|
||||
}
|
||||
x += '</table>';
|
||||
if (x != '') { sections.push({ name: "Memory", html: x, img: 'ram'}); }
|
||||
}
|
||||
}
|
||||
|
||||
// Storage
|
||||
if (hardware.identifiers && ident.storage_devices) {
|
||||
var x = '';
|
||||
@ -6154,6 +6159,45 @@
|
||||
if (x != '') { sections.push({ name: "Storage", html: x, img: 'storage' }); }
|
||||
}
|
||||
|
||||
// Volumes and Bitlocker
|
||||
if (hardware.windows && hardware.windows.volumes) {
|
||||
var x = '';
|
||||
for (var i in hardware.windows.volumes) {
|
||||
var m = hardware.windows.volumes[i];
|
||||
x += '<tr><td><div class=style10 style=border-radius:5px;padding:8px>';
|
||||
x += '<div style=margin-bottom:3px><b>' + i + ':' + (((m.name == null) || (m.name == '')) ? '' : (' - ' + EscapeHtml(m.name))) + '</b></div>';
|
||||
if (m.size) {
|
||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
var j = parseInt(Math.floor(Math.log(Math.abs(m.size)) / Math.log(1024)), 10);
|
||||
var fsize = (j === 0 ? `${m.size} ${sizes[j]}` : `${(m.size / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
|
||||
x += addDetailItem("Capacity", EscapeHtml(fsize), s);
|
||||
}
|
||||
if (m.sizeremaining) {
|
||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
var j = parseInt(Math.floor(Math.log(Math.abs(m.sizeremaining)) / Math.log(1024)), 10);
|
||||
var fsize = (j === 0 ? `${m.sizeremaining} ${sizes[j]}` : `${(m.sizeremaining / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
|
||||
x += addDetailItem("Capacity Remaining", EscapeHtml(fsize), s);
|
||||
}
|
||||
if (m.type) {
|
||||
var type = (m.removable == true ? "Removable" : (m.cdrom == true ? "CD-ROM" : ''));
|
||||
x += addDetailItem("File System", (type != '' ? (type + ' / ') : '') + (m.type == 'Unknown' ? "Unknown" : EscapeHtml(m.type)), s);
|
||||
}
|
||||
|
||||
if (m.protectionStatus || m.volumeStatus) {
|
||||
var bitlockerState = [];
|
||||
if (m.protectionStatus) bitlockerState.push("Enabled");
|
||||
if (m.volumeStatus && m.volumeStatus == 'FullyDecrypted') bitlockerState.push("Fully Decrypted");
|
||||
if (m.volumeStatus && m.volumeStatus == 'EncryptionInProgress') bitlockerState.push("Encryption In Progress");
|
||||
if (m.volumeStatus && m.volumeStatus == 'FullyEncrypted') bitlockerState.push("Fully Encrypted");
|
||||
bitlockerState = bitlockerState.join(' - ');
|
||||
if (m.recoveryPassword) { bitlockerState += addKeyLink('', 'deviceDetailsShowBitlockerInfo(\"' + encodeURIComponentEx(i) + '\",\"' + encodeURIComponentEx(m.identifier) + '\",\"' + encodeURIComponentEx(m.recoveryPassword) + '\")'); }
|
||||
x += addDetailItem("BitLocker", bitlockerState, s);
|
||||
}
|
||||
x += '</div>';
|
||||
}
|
||||
if (x != '') { sections.push({ name: "Storage Volumes", html: '<table style=width:100%>' + x + '</table>', img: 'storage'}); }
|
||||
}
|
||||
|
||||
// Render the sections
|
||||
var x = '';
|
||||
for (var i in sections) {
|
||||
@ -6174,6 +6218,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
function deviceDetailsShowBitlockerInfo(drive, identifier, password) {
|
||||
if (xxdialogMode) return false;
|
||||
var x = '<div><p>' + "Identifier" + '</p><p style=user-select:text;font-weight:bold>' + (identifier ? decodeURIComponent(identifier) : "Unknown") + '</p>';
|
||||
x += '<p>' + "Recovery Password" + '</p><p style=user-select:text;font-weight:bold>' + (password ? decodeURIComponent(password) : "Unknown") + '</p></div>';
|
||||
setDialogMode(2, decodeURIComponent(drive) + ': ' + "BitLocker Information", 1, null, x, '');
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// CONSOLE
|
||||
@ -7116,6 +7167,8 @@
|
||||
function addHtmlValue4(t, v) { return '<table style=width:100%><td style=width:120px>' + t + '<td style=text-align:right><b>' + v + '</b></table>'; }
|
||||
function addLink(x, f) { return '<a style=cursor:pointer;text-decoration:none onclick=\'' + f + '\'>♦ ' + x + '</a>'; }
|
||||
function addLinkConditional(x, f, c) { if (c) return addLink(x, f); return x; }
|
||||
function addKeyLink(x, f) { return '<span tabindex=0 style=cursor:pointer;text-decoration:none onclick=' + f + ' onkeypress="if (event.key==\'Enter\') { ' + f + ' } ">' + x + ' <img class=hoverButton src=images/key16.png></span>'; }
|
||||
function addKeyLinkConditional(x, f, c) { if (c) return addKeyLink(x, f); return x; }
|
||||
function passwordcheck(p) { var re = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()]).{8,}/; return re.test(p); }
|
||||
function getFileSizeStr(size) { if (typeof size != 'number') { size = 0; } if (size == 1) return "1 byte"; return format('{0} bytes', size); }
|
||||
function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
|
||||
|
@ -684,6 +684,7 @@
|
||||
<input id="deskActionsBtn" type=button title="Perform power actions on the device" onkeypress="return false" onkeydown="return false" value=Actions onclick=deviceActionFunction() class="mR" />
|
||||
<input id="deskActionsSettings" type="button" value="Settings..." title="Edit remote desktop settings" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" class="mR" />
|
||||
<input type="button" title="Change the power state of the remote machine" onkeypress="return false" onkeydown="return false" value="Power Actions..." onclick="showPowerActionDlg()" style="display:none" />
|
||||
<div id="desktopCustomUpperRight" style="float:left;margin-right:6px"></div>
|
||||
<div id="desktopCustomUiButtons" style="float:left"></div>
|
||||
</div>
|
||||
<div>
|
||||
@ -868,6 +869,7 @@
|
||||
<input type=button style="margin-right:2px" disabled="disabled" id=p13CopyButton value="Copy" onclick="p13copyFile(0)" />
|
||||
<input type=button style="margin-right:2px" disabled="disabled" id=p13PasteButton value="Paste" onclick="p13pasteFile()" />
|
||||
<input type=button style="margin-right:2px" disabled="disabled" id=p13ZipButton value="Zip" onclick="p13zipFiles()" />
|
||||
<input type=button style="margin-right:2px" disabled="disabled" id=p13UnzipButton value="Unzip" onclick="p13unzipFile()" />
|
||||
<input type=button style="margin-right:2px" disabled="disabled" id=p13RefreshButton value="Refresh" onclick="p13folderup(9999)" />
|
||||
<input type=button style="margin-right:2px" disabled="disabled" id=p13FindButton value="Find" onclick="p13findfile()" />
|
||||
<input type=button style="margin-right:2px" disabled="disabled" id=p13GoToFolderButton value="GoTo" onclick="p13gotofolder()" />
|
||||
@ -2329,7 +2331,23 @@
|
||||
function setSessionActivity() { sessionActivity = Date.now(); QH('idleTimeoutNotify', ''); }
|
||||
function checkIdleSessionTimeout() {
|
||||
var delta = (Date.now() - sessionActivity);
|
||||
if (delta > serverinfo.timeout) { window.location.href = 'logout'; } else {
|
||||
if (delta > serverinfo.timeout) {
|
||||
if (desktop != null) { // Disconnect remote desktop
|
||||
desktop.Stop();
|
||||
webRtcDesktopReset();
|
||||
desktopNode = desktop = null;
|
||||
if (pluginHandler != null) { pluginHandler.callHook('onDesktopDisconnect'); }
|
||||
}
|
||||
if (terminal != null) { // Disconnect terminal
|
||||
terminal.Stop();
|
||||
terminal = null;
|
||||
}
|
||||
if (files != null) { // Disconnect files
|
||||
files.Stop();
|
||||
files = null;
|
||||
}
|
||||
window.location.href = 'logout';
|
||||
} else {
|
||||
var ds = Math.round((serverinfo.timeout - delta) / 1000);
|
||||
if (ds <= 60) {
|
||||
QH('idleTimeoutNotify', '<br />' + format((ds == 1)?"1 second until disconnect":"{0} seconds until disconnect", ds));
|
||||
@ -5435,8 +5453,8 @@
|
||||
if (serverinfo.https == true) { portStr = (serverinfo.port == 443)?'':(':' + serverinfo.port); } else { portStr = (serverinfo.port == 80) ? '' : (':' + serverinfo.port); }
|
||||
|
||||
// Add Linux/macOS binary installer option
|
||||
var binaryInstallAgentsOrder = [ 6, 5, 10005, 25, 26, 28, 30, 32, 36, 37, 40, 41 ];
|
||||
var binaryInstallAgents = { 5 : 'Linux x86-32', 6 : 'Linux x86-64', 10005 : 'Apple OSX Universal', 25 : 'Linux ARM-HF, Rasberry Pi', 26 : 'Linux ARM64-HF', 28: 'Linux MIPS24KC (OpenWRT)', 30 : 'FreeBSD x86-64', 32: 'Linux ARM 64 bit (glibc/2.24 NOKVM)', 36: 'OpenWRT x86-64', 37: 'OpenBSD x86-64', 40: 'Linux MIPSEL24KC (OpenWRT)', 41: 'ARMADA/CORTEX-A53/MUSL (OpenWRT)' };
|
||||
var binaryInstallAgentsOrder = [ 6, 5, 10005, 25, 26, 28, 30, 32, 36, 37, 40, 41, 16, 29 ];
|
||||
var binaryInstallAgents = { 6 : 'Linux x86-64', 5 : 'Linux x86-32', 10005 : 'Apple OSX Universal', 25 : 'Linux ARM-HF, Rasberry Pi', 26 : 'Linux ARM64-HF', 28: 'Linux MIPS24KC (OpenWRT)', 30 : 'FreeBSD x86-64', 32: 'Linux ARM 64 bit (glibc/2.24 NOKVM)', 36: 'OpenWRT x86-64', 37: 'OpenBSD x86-64', 40: 'Linux MIPSEL24KC (OpenWRT)', 41: 'ARMADA/CORTEX-A53/MUSL (OpenWRT)', 16: 'Apple macOS x86-64', 29: 'Apple macOS ARM-64' };
|
||||
for (var i in binaryInstallAgentsOrder) { moreoptions += '<option value=' + binaryInstallAgentsOrder[i] + '>' + binaryInstallAgents[binaryInstallAgentsOrder[i]] + '</option>' }
|
||||
x += '<div id=aginsSysTypeDiv>';
|
||||
x += addHtmlValue("System Type", '<select id=aginsSysType onchange=addAgentToMeshClick() style=width:236px>' + moreoptions + '</select>');
|
||||
@ -7538,9 +7556,9 @@
|
||||
x += '<input type=button value="' + "Log Event" + '" title="' + "Write an event for this device" + '" onclick=writeDeviceEvent("' + encodeURIComponentEx(node._id) + '") />';
|
||||
if ((node.mtype == 2) && (connectivity & 1) && ((meshrights & 131072) != 0)) { x += '<input type=button cmenu=deskPreConfigScriptContextMenu value="' + "Run" + '" title="' + "Run commands on this device" + '" onclick=runDeviceCmd("' + encodeURIComponentEx(node._id) + '") />'; }
|
||||
if (node.mtype != 4) {
|
||||
if ((meshrights & 8) && ((connectivity & 1) || ((node.pmt == 1) && ((features2 & 2) != 0)))) { x += '<input type=button value="' + "Message" + '" title="' + "Display a text message on the remote device" + '" onclick=deviceMessageFunction() />'; }
|
||||
if ((meshrights & 8) && (connectivity & 1) && ((meshrights & 16384) != 0) || ((node.pmt == 1) && ((features2 & 2) != 0))) { x += '<input type=button value="' + "Message" + '" title="' + "Display a text message on the remote device" + '" onclick=deviceMessageFunction() />'; }
|
||||
//if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += '<input type=button value=Toast title="' + "Display a text message of the remote device" + '" onclick=deviceToastFunction() />'; }
|
||||
if ((meshrights & 8) && (connectivity & 1) || ((node.pmt == 1) && ((features2 & 2) != 0))) { x += '<input type=button value="' + "Chat" + '" title="' + "Open chat window to this computer" + '" onclick=deviceChat(event) />'; }
|
||||
if ((meshrights & 8) && (connectivity & 1) && ((meshrights & 16384) != 0) || ((node.pmt == 1) && ((features2 & 2) != 0))) { x += '<input type=button value="' + "Chat" + '" title="' + "Open chat window to this computer" + '" onclick=deviceChat(event) />'; }
|
||||
if ((serverinfo != null) && (serverinfo.altmessenging != null) && (meshrights & 8) && (connectivity & 1)) {
|
||||
for (var i in serverinfo.altmessenging) {
|
||||
var am = serverinfo.altmessenging[i];
|
||||
@ -8110,7 +8128,7 @@
|
||||
|
||||
function deviceMessageFunction() {
|
||||
if (xxdialogMode) return;
|
||||
var x = '<div style=margin-bottom:4px>Display a message box on the remote device.</div>';
|
||||
var x = '<div style=margin-bottom:4px>' + "Display a message box on the remote device" + '</div>';
|
||||
x += '<textarea id=d2devMessage style=background-color:#fcf3cf;width:100%;height:80px;resize:none;overflow-y:scroll;box-sizing:border-box;margin-bottom:4px></textarea>';
|
||||
x += '<select style=width:100% id=d2devTimeout>';
|
||||
x += '<option value=2 selected>' + "Show for 2 Minutes (Default)" + '</option>';
|
||||
@ -8255,7 +8273,7 @@
|
||||
x += addHtmlValue("Start Time", '<input id=d2timeStartSelector style=float:right;width:250px class=flatpickr type="text" placeholder="' + "Select Date & Time..." + '" data-id="altinput">');
|
||||
x += addHtmlValue("Duration", '<select id=d2inviteDuration style=float:right;width:250px>' + z + '</select>');
|
||||
x += '</div>';
|
||||
if (currentNode.agent.caps & 1) { x += '<div id=d2userConsentSelector>' + addHtmlValue("User Consent", '<select id=d2userConsent style=float:right;width:250px><option value=1>' + "Prompt for consent" + '</option><option value=0>' + "Notify Only" + '</option></select>') + '</div>'; }
|
||||
if (currentNode.agent.caps & 1) { x += '<div id=d2userConsentSelector>' + addHtmlValue("User Consent", '<select id=d2userConsent style=float:right;width:250px><option value=0>' + "Notify Only" + '<option value=1>' + "Prompt for consent" + '</option><option value=2>' + "No Consent" + '</option></select>') + '</div>'; }
|
||||
x += '<div id=d2httpPortSelector>' + addHtmlValue("Port", '<input id=d2httpPort style=float:right;width:250px value=80 onkeyup=showShareDeviceValidate()></input>') + '</div>';
|
||||
x += '<div id=d2httpsPortSelector>' + addHtmlValue("Port", '<input id=d2httpsPort style=float:right;width:250px value=443 onkeyup=showShareDeviceValidate()></input>') + '</div>';
|
||||
setDialogMode(2, "Share Device", 3, showShareDeviceEx, x);
|
||||
@ -8291,14 +8309,17 @@
|
||||
if (q & 1) {
|
||||
consent |= 0x0002; // Terminal notify
|
||||
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 1)) { consent |= 0x0010; } // Terminal prompt for user consent
|
||||
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 2)) { consent = 0; } // Terminal with no user consent
|
||||
}
|
||||
if (q & 2) {
|
||||
consent |= 0x0041; // Desktop connection toolbar + Desktop notify
|
||||
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 1)) { consent |= 0x0008; } // Desktop prompt for user consent
|
||||
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 2)) { consent = 0; } // Desktop with no user consent
|
||||
}
|
||||
if (q & 4) {
|
||||
consent |= 0x0004; // Files notify
|
||||
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 1)) { consent |= 0x0020; } // Files prompt for user consent
|
||||
if ((currentNode.agent.caps & 1) && (Q('d2userConsent').value == 2)) { consent = 0; } // Files prompt for user consent
|
||||
}
|
||||
|
||||
if (Q('d2timeRange').value == 0) {
|
||||
@ -8989,7 +9010,11 @@
|
||||
var online = ((currentNode.conn & 1) != 0); // If Agent (1) connected, enable remote desktop
|
||||
QE('connectbutton1', online);
|
||||
QE('connectbutton1r', online || (currentNode.mtype == 3));
|
||||
Q('connectbutton1r').value = 'RDP Connect' + ((currentNode.rdpport && currentNode.rdpport != 3389) ? ' ('+currentNode.rdpport + ')' : '');
|
||||
if (currentNode.rdpport && currentNode.rdpport != 3389) {
|
||||
QH('desktopCustomUpperRight', '<a style="cursor:pointer;line-height:22px" onclick="cmaltportaction(1,event)">' + format("RDP Port {0}", (currentNode.rdpport?currentNode.rdpport:3389)) + '</a>');
|
||||
} else {
|
||||
QH('desktopCustomUpperRight', '');
|
||||
}
|
||||
var hwonline = ((currentNode.conn & 6) != 0); // If CIRA (2) or AMT (4) connected, enable hardware terminal
|
||||
QE('connectbutton1h', hwonline);
|
||||
QV('deskFocusBtn', (desktop != null) && (desktop.contype == 2) && (deskState != 0) && (desktopsettings.showfocus));
|
||||
@ -9024,9 +9049,9 @@
|
||||
QV('DeskRunButton', ((rights & 131072) != 0) && online);
|
||||
QV('DeskSaveImageButton', (deskState == 3) && (Q('Desk')['toBlob'] != null) && ((features2 & 0x400) == 0));
|
||||
QV('DeskRecordButton', (deskState == 3) && (Q('Desk')['toBlob'] != null) && (desktop.m.StartRecording != null) && ((features2 & 0x400) == 0));
|
||||
QV('DeskChatButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (inputAllowed) && (currentNode.agent) && online);
|
||||
QV('DeskNotifyButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (currentNode.agent) && online);
|
||||
QV('DeskLockButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (currentNode.agent) && (deskState == 3));
|
||||
QV('DeskChatButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && online);
|
||||
QV('DeskNotifyButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && online);
|
||||
QV('DeskLockButton', ((rights & 16384) != 0) && (browserfullscreen == false) && (currentNode.agent) && (currentNode.agent.id < 5) && (inputAllowed) && (deskState == 3));
|
||||
QV('DeskToolsButton', (currentNode.agent) && online);
|
||||
QE('DeskToolsButton', inputAllowed);
|
||||
QV('DeskOpenWebButton', (browserfullscreen == false) && (inputAllowed) && (currentNode.agent) && online);
|
||||
@ -10938,10 +10963,16 @@
|
||||
setDialogMode(0); // Close the dialog box
|
||||
} else if ((data.msg == 'zipping') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
|
||||
// Show the dialog box message
|
||||
setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + "Compressing files..." + '<div>', 'fileMsgDialog');
|
||||
setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + "Compressing files..." + '</div>', 'fileMsgDialog');
|
||||
} else if ((data.msg == 'unzipping') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
|
||||
// Show the dialog box message
|
||||
setDialogMode(2, "File Operation", 10, null, '<div style=margin:10px>' + "Unzipping file..." + '</div>', 'fileMsgDialog');
|
||||
} else if ((data.msg == 'unziperror') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
|
||||
// Show the dialog box message
|
||||
setDialogMode(2, "File Operation", 10, null, '<div style=margin:10px>' + "Unzipping Error" + '</div><br />' + EscapeHtml(data.error), 'fileMsgDialog');
|
||||
} else if ((data.msg == 'zippingFile') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
|
||||
// Show the dialog box message
|
||||
setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + EscapeHtml(data.file) + '<div><br /><progress value=' + EscapeHtml(data.progress) + ' style=width:100% max=100 />', 'fileMsgDialog');
|
||||
setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + EscapeHtml(data.file) + '</div><br /><progress value=' + EscapeHtml(data.progress) + ' style=width:100% max=100 />', 'fileMsgDialog');
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -11181,6 +11212,7 @@
|
||||
QE('p13CutButton', false);
|
||||
QE('p13CopyButton', false);
|
||||
QE('p13ZipButton', false);
|
||||
QE('p13UnZipButton', false);
|
||||
QE('p13PasteButton', false);
|
||||
QE('p13GoToFolderButton', false);
|
||||
QE('p13DownloadButton', false);
|
||||
@ -11199,6 +11231,7 @@
|
||||
QE('p13CutButton', advancedFeatures && (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
||||
QE('p13CopyButton', advancedFeatures && (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
||||
QE('p13ZipButton', advancedFeatures && (cc > 0) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
||||
QE('p13UnzipButton', advancedFeatures && (cc == 1) && (sfc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)) && p13getFileSelAllowedExt('.zip'));
|
||||
QE('p13PasteButton', advancedFeatures && ((p13filetreelocation.length > 0) || (winAgent == false)) && ((p13clipboard != null) && (p13clipboard.length > 0)));
|
||||
QE('p13GoToFolderButton', true);
|
||||
QE('p13DownloadButton', advancedFeatures && (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
|
||||
@ -11214,12 +11247,14 @@
|
||||
QV('p13CutButton', filesNode.mtype != 3);
|
||||
QV('p13CopyButton', filesNode.mtype != 3);
|
||||
QV('p13ZipButton', filesNode.mtype != 3);
|
||||
QV('p13UnzipButton', filesNode.mtype != 3);
|
||||
QV('p13PasteButton', filesNode.mtype != 3);
|
||||
}
|
||||
|
||||
function p13getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
|
||||
function p13getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
|
||||
function p13getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
|
||||
function p13getFileSelAllowedExt(ext) { var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (!p13filetree.dir[checkboxes[i].value].n.endsWith(ext))) return false; } return true; }
|
||||
function p13selectallfile() { var nv = (p13getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p13setActions(); }
|
||||
function p13createfolder() { setDialogMode(2, "New Folder", 3, p13createfolderEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />'); focusTextBox('p13renameinput'); p13fileNameCheck(); }
|
||||
function p13createfolderEx() { files.sendText({ action: 'mkdir', reqid: 1, path: p13filetreelocation.join('/') + '/' + Q('p13renameinput').value }); p13folderup(999); }
|
||||
@ -11243,6 +11278,24 @@
|
||||
}
|
||||
}
|
||||
|
||||
function p13unzipFile() {
|
||||
var dest, input, checkboxes = document.getElementsByName('fd');
|
||||
for (var i = 0; i < checkboxes.length; i++) {
|
||||
if (checkboxes[i].checked) {
|
||||
var slash = isWindowsNode(currentNode) ? '\\' : '/';
|
||||
dest = (isWindowsNode(currentNode) ? '' : '/') + p13filetreelocation.join(slash) + slash + p13filetree.dir[checkboxes[i].value].n.split('.zip')[0] + slash;
|
||||
input = (isWindowsNode(currentNode) ? '' : '/') + p13filetreelocation.join(slash) + slash + p13filetree.dir[checkboxes[i].value].n;
|
||||
}
|
||||
}
|
||||
setDialogMode(2, "Unzip To Folder", 3, p13unzipFileEx, '<input type=text id=p13unzipfolderinput maxlength=64 style=width:100% value="' + dest + '" />', { action: 'unzip', input: input });
|
||||
focusTextBox('p13unzipfolderinput');
|
||||
}
|
||||
|
||||
function p13unzipFileEx(a, tag) {
|
||||
tag.dest = Q('p13unzipfolderinput').value;
|
||||
files.sendText(tag);
|
||||
}
|
||||
|
||||
function p13zipFiles() {
|
||||
var inputFiles = [], checkboxes = document.getElementsByName('fd');
|
||||
for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { inputFiles.push(p13filetree.dir[checkboxes[i].value].n); } }
|
||||
@ -11698,8 +11751,8 @@
|
||||
data: {
|
||||
labels: [],
|
||||
datasets: [
|
||||
{ label: 'CPU', backgroundColor: 'rgba(134, 16, 158, .5)', borderColor: 'rgb(134, 16, 158)', data: [], fill: true },
|
||||
{ label: 'Memory', backgroundColor: 'rgba(255, 99, 132, .5)', borderColor: 'rgb(255, 99, 132)', data: [], fill: true }
|
||||
{ label: "CPU", backgroundColor: 'rgba(134, 16, 158, .5)', borderColor: 'rgb(134, 16, 158)', data: [], fill: true },
|
||||
{ label: "Memory", backgroundColor: 'rgba(255, 99, 132, .5)', borderColor: 'rgb(255, 99, 132)', data: [], fill: true }
|
||||
] },
|
||||
options: {
|
||||
events: ['click'],
|
||||
@ -12019,9 +12072,9 @@
|
||||
if (tpm.SpecVersion) { x += addDetailItem("SpecVersion", parseFloat(EscapeHtml(tpm.SpecVersion)).toFixed(1), s); }
|
||||
if (tpm.ManufacturerId) { x += addDetailItem("ManufacturerId", EscapeHtml(tpm.ManufacturerId), s); }
|
||||
if (tpm.ManufacturerVersion) { x += addDetailItem("ManufacturerVersion", EscapeHtml(tpm.ManufacturerVersion), s); }
|
||||
if (tpm.IsActivated != null) { x += addDetailItem("IsActivated", EscapeHtml(tpm.IsActivated), s); }
|
||||
if (tpm.IsEnabled != null) { x += addDetailItem("IsEnabled", EscapeHtml(tpm.IsEnabled), s); }
|
||||
if (tpm.IsOwned != null) { x += addDetailItem("IsOwned", EscapeHtml(tpm.IsOwned), s); }
|
||||
if (tpm.IsActivated != null) { x += addDetailItem("IsActivated", (tpm.IsActivated ? "Yes" : "No"), s); }
|
||||
if (tpm.IsEnabled != null) { x += addDetailItem("IsEnabled", (tpm.IsEnabled ? "Yes" : "No"), s); }
|
||||
if (tpm.IsOwned != null) { x += addDetailItem("IsOwned", (tpm.IsOwned ? "Yes" : "No"), s); }
|
||||
if (x != '') { sections.push({ name: "TPM", html: x, img: 'tpm64.png'}); }
|
||||
}
|
||||
|
||||
@ -12070,6 +12123,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
if (hardware.darwin) {
|
||||
if (hardware.darwin.memory && (hardware.darwin.memory.length > 0)) {
|
||||
var x = '';
|
||||
x += '<table style=width:100%>';
|
||||
for (var i in hardware.darwin.memory) {
|
||||
var m = hardware.darwin.memory[i];
|
||||
if(m.Size && (m.Size == 'No Module Installed')) continue;
|
||||
x += '<tr><td><div class=style10 style=border-radius:5px;padding:8px>';
|
||||
x += '<div style=margin-bottom:3px><b>' + EscapeHtml((m.DeviceLocator ? m.DeviceLocator : 'Unknown')) + '</b></div>';
|
||||
if (m.Size && m.Speed) { x += addDetailItem("Capacity / Speed", format("{0}, {1}", m.Size, m.Speed), s); }
|
||||
else if (m.Size) { x += addDetailItem("Capacity", format("{0}", (m.Size)), s); }
|
||||
if (m.PartNumber) { x += addDetailItem("Part Number", EscapeHtml((m.Manufacturer && m.Manufacturer != '')?(m.Manufacturer + ', '):'') + EscapeHtml(m.PartNumber), s); }
|
||||
x += '</div>';
|
||||
}
|
||||
x += '</table>';
|
||||
if (x != '') { sections.push({ name: "Memory", html: x, img: 'ram64.png'}); }
|
||||
}
|
||||
}
|
||||
|
||||
// Storage
|
||||
if (hardware.identifiers && hardware.identifiers.storage_devices) {
|
||||
var x = '';
|
||||
@ -12113,12 +12185,23 @@
|
||||
var fsize = (j === 0 ? `${m.size} ${sizes[j]}` : `${(m.size / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
|
||||
x += addDetailItem("Capacity", EscapeHtml(fsize), s);
|
||||
}
|
||||
if (m.type) { x += addDetailItem("File System", (m.removable == true ? ("Removable" + ' / ') : '') + EscapeHtml(m.type), s); }
|
||||
if (m.sizeremaining) {
|
||||
var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
|
||||
var j = parseInt(Math.floor(Math.log(Math.abs(m.sizeremaining)) / Math.log(1024)), 10);
|
||||
var fsize = (j === 0 ? `${m.sizeremaining} ${sizes[j]}` : `${(m.sizeremaining / (1024 ** j)).toFixed(2)} ${sizes[j]}`);
|
||||
x += addDetailItem("Capacity Remaining", EscapeHtml(fsize), s);
|
||||
}
|
||||
if (m.type) {
|
||||
var type = (m.removable == true ? "Removable" : (m.cdrom == true ? "CD-ROM" : ''));
|
||||
x += addDetailItem("File System", (type != '' ? (type + ' / ') : '') + (m.type == 'Unknown' ? "Unknown" : EscapeHtml(m.type)), s);
|
||||
}
|
||||
|
||||
if (m.protectionStatus || m.volumeStatus) {
|
||||
var bitlockerState = [];
|
||||
if (m.protectionStatus) bitlockerState.push("Enabled");
|
||||
if (m.volumeStatus) bitlockerState.push(EscapeHtml(m.volumeStatus));
|
||||
if (m.volumeStatus && m.volumeStatus == 'FullyDecrypted') bitlockerState.push("Fully Decrypted");
|
||||
if (m.volumeStatus && m.volumeStatus == 'EncryptionInProgress') bitlockerState.push("Encryption In Progress");
|
||||
if (m.volumeStatus && m.volumeStatus == 'FullyEncrypted') bitlockerState.push("Fully Encrypted");
|
||||
bitlockerState = bitlockerState.join(' - ');
|
||||
if (m.recoveryPassword) { bitlockerState += addKeyLink('', 'deviceDetailsShowBitlockerInfo(\"' + encodeURIComponentEx(i) + '\",\"' + encodeURIComponentEx(m.identifier) + '\",\"' + encodeURIComponentEx(m.recoveryPassword) + '\")'); }
|
||||
x += addDetailItem("BitLocker", bitlockerState, s);
|
||||
|
@ -2815,7 +2815,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
|
||||
obj.authenticate(req.query.user, req.query.pass, domain, function (err, userid, passhint, loginOptions) {
|
||||
// 2FA is not supported in URL authentication method. If user has 2FA enabled, this login method fails.
|
||||
var user = obj.users[userid];
|
||||
if (checkUserOneTimePasswordRequired(domain, user, req, loginOptions) == true) {
|
||||
if ((err == null) && checkUserOneTimePasswordRequired(domain, user, req, loginOptions) == true) {
|
||||
handleRootRequestEx(req, res, domain, direct);
|
||||
} else if ((userid != null) && (err == null)) {
|
||||
// Login success
|
||||
|
Loading…
Reference in New Issue
Block a user