@livedesk/client 0.1.130 → 0.1.132
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/livedesk-client-node.js +66 -18
- package/fast/linux-x64/livedesk-client-fast.dll +0 -0
- package/fast/linux-x64/livedesk-client-fast.pdb +0 -0
- package/fast/osx-arm64/livedesk-client-fast.dll +0 -0
- package/fast/osx-arm64/livedesk-client-fast.pdb +0 -0
- package/fast/osx-x64/livedesk-client-fast.dll +0 -0
- package/fast/osx-x64/livedesk-client-fast.pdb +0 -0
- package/fast/win-x64/livedesk-client-fast.dll +0 -0
- package/fast/win-x64/livedesk-client-fast.pdb +0 -0
- package/package.json +1 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import net from 'net';
|
|
4
4
|
import os from 'os';
|
|
@@ -197,7 +197,7 @@ function parseArgs(argv) {
|
|
|
197
197
|
return result;
|
|
198
198
|
}
|
|
199
199
|
|
|
200
|
-
function parseManagerAddress(value) {
|
|
200
|
+
function parseManagerAddress(value) {
|
|
201
201
|
let text = String(value || DEFAULT_MANAGER).trim();
|
|
202
202
|
text = text.replace(/^tcp:\/\//i, '');
|
|
203
203
|
const separator = text.lastIndexOf(':');
|
|
@@ -210,11 +210,25 @@ function parseManagerAddress(value) {
|
|
|
210
210
|
|
|
211
211
|
const host = text.slice(0, separator).trim() || '127.0.0.1';
|
|
212
212
|
const port = Number(text.slice(separator + 1));
|
|
213
|
-
return {
|
|
214
|
-
host,
|
|
215
|
-
port: Number.isFinite(port) ? port : 5197
|
|
216
|
-
};
|
|
217
|
-
}
|
|
213
|
+
return {
|
|
214
|
+
host,
|
|
215
|
+
port: Number.isFinite(port) ? port : 5197
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function isPrivateLanHost(host) {
|
|
220
|
+
const value = String(host || '').trim().toLowerCase().replace(/^\[|\]$/g, '');
|
|
221
|
+
if (!value || value === 'localhost' || value === '::1') return true;
|
|
222
|
+
if (net.isIPv4(value)) {
|
|
223
|
+
const octets = value.split('.').map(Number);
|
|
224
|
+
return octets[0] === 10
|
|
225
|
+
|| (octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31)
|
|
226
|
+
|| (octets[0] === 192 && octets[1] === 168)
|
|
227
|
+
|| octets[0] === 127;
|
|
228
|
+
}
|
|
229
|
+
if (net.isIPv6(value)) return value.startsWith('fc') || value.startsWith('fd') || value.startsWith('fe80:');
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
218
232
|
|
|
219
233
|
function normalizeDeviceId(value) {
|
|
220
234
|
return String(value || '').trim().replace(/[^a-zA-Z0-9_.:-]/g, '-').slice(0, 128);
|
|
@@ -1267,10 +1281,27 @@ function normalizeNodeAgentTaskResult(result) {
|
|
|
1267
1281
|
}
|
|
1268
1282
|
|
|
1269
1283
|
const NODE_AGENT_OPERATIONS = new Set(['process.control', 'service.control', 'application.launch', 'application.close', 'file.read', 'file.write', 'file.delete', 'file.list', 'command.run', 'script.run', 'software.install', 'network.status', 'system.power', 'system.configure', 'logs.collect']);
|
|
1270
|
-
|
|
1271
|
-
|
|
1284
|
+
|
|
1285
|
+
function remotePolicyAllows(options, command) {
|
|
1286
|
+
const policy = options.effectivePolicy;
|
|
1287
|
+
if (!policy || typeof policy !== 'object') return { ok: true };
|
|
1288
|
+
if (policy.accessMode === 'block-remote-access') return { ok: false, error: 'remote-access-blocked-by-settings' };
|
|
1289
|
+
const required = command === 'input.control'
|
|
1290
|
+
? ['allowControl']
|
|
1291
|
+
: command.startsWith('file.transfer')
|
|
1292
|
+
? ['allowFileTransfer']
|
|
1293
|
+
: command === 'audio.start'
|
|
1294
|
+
? ['allowRemoteAudio']
|
|
1295
|
+
: command === 'agent.task' || NODE_AGENT_OPERATIONS.has(command)
|
|
1296
|
+
? ['allowAgent']
|
|
1297
|
+
: [];
|
|
1298
|
+
const denied = required.find(key => policy[key] === false);
|
|
1299
|
+
return denied ? { ok: false, error: `${denied}-blocked-by-settings` } : { ok: true };
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
async function handleRemoteCommand(socket, options, message, nextFrameSeq, activeStreams) {
|
|
1272
1303
|
const command = String(message.command || '');
|
|
1273
|
-
if (command === 'ping') {
|
|
1304
|
+
if (command === 'ping') {
|
|
1274
1305
|
writeJsonLine(socket, {
|
|
1275
1306
|
type: 'command.result',
|
|
1276
1307
|
commandId: message.commandId,
|
|
@@ -1279,8 +1310,19 @@ async function handleRemoteCommand(socket, options, message, nextFrameSeq, activ
|
|
|
1279
1310
|
at: new Date().toISOString()
|
|
1280
1311
|
}
|
|
1281
1312
|
});
|
|
1282
|
-
return;
|
|
1283
|
-
}
|
|
1313
|
+
return;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
const policyDecision = remotePolicyAllows(options, command);
|
|
1317
|
+
if (!policyDecision.ok) {
|
|
1318
|
+
writeJsonLine(socket, {
|
|
1319
|
+
type: 'command.result',
|
|
1320
|
+
commandId: message.commandId,
|
|
1321
|
+
error: policyDecision.error,
|
|
1322
|
+
result: { ok: false, status: 'failed', error: policyDecision.error }
|
|
1323
|
+
});
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1284
1326
|
|
|
1285
1327
|
if (NODE_AGENT_OPERATIONS.has(command)) {
|
|
1286
1328
|
if (!options.taskEnabled) {
|
|
@@ -1544,9 +1586,12 @@ async function handleRemoteCommand(socket, options, message, nextFrameSeq, activ
|
|
|
1544
1586
|
});
|
|
1545
1587
|
}
|
|
1546
1588
|
|
|
1547
|
-
function connectOnce(options, deviceId) {
|
|
1548
|
-
const manager = parseManagerAddress(options.manager);
|
|
1549
|
-
|
|
1589
|
+
function connectOnce(options, deviceId) {
|
|
1590
|
+
const manager = parseManagerAddress(options.manager);
|
|
1591
|
+
if (!isPrivateLanHost(manager.host) && !isTruthy(process.env.LIVEDESK_ALLOW_UNENCRYPTED_LAN)) {
|
|
1592
|
+
return Promise.reject(new Error('Plain TCP LiveDesk connections are limited to loopback/private LAN. Use an encrypted endpoint for external connections.'));
|
|
1593
|
+
}
|
|
1594
|
+
return new Promise((resolve, reject) => {
|
|
1550
1595
|
const socket = net.createConnection({
|
|
1551
1596
|
host: manager.host,
|
|
1552
1597
|
port: manager.port
|
|
@@ -1636,9 +1681,12 @@ function connectOnce(options, deviceId) {
|
|
|
1636
1681
|
continue;
|
|
1637
1682
|
}
|
|
1638
1683
|
|
|
1639
|
-
const message = JSON.parse(line);
|
|
1640
|
-
if (message.type === 'welcome') {
|
|
1641
|
-
|
|
1684
|
+
const message = JSON.parse(line);
|
|
1685
|
+
if (message.type === 'welcome') {
|
|
1686
|
+
options.effectivePolicy = message.effectivePolicy && typeof message.effectivePolicy === 'object'
|
|
1687
|
+
? message.effectivePolicy
|
|
1688
|
+
: null;
|
|
1689
|
+
console.log(`Connected to LiveDesk Hub as ${options.name} (${deviceId})`);
|
|
1642
1690
|
writeJsonLine(socket, {
|
|
1643
1691
|
type: 'status',
|
|
1644
1692
|
status: getStatus(options)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|