AddLocalDevice and AddAmtDevice to meshctrl.js #6473
Signed-off-by: si458 <simonsmith5521@gmail.com>
si458 committed
Oct 25, 2024 at 10:34 UTC
141bec559fb291a0f361826d3000851a118e08cb
2 files changed
+170
-57
meshctrl.js
+93
-1
@@ -16,7 +16,7 @@ var settings = {};
16
const crypto = require('crypto');
17
const args = require('minimist')(process.argv.slice(2));
18
const path = require('path');
19
-const possibleCommands = ['edituser', 'listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'listevents', 'logintokens', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'editdevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'removedevice', 'editdevice', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand', 'shell', 'upload', 'download', 'deviceopenurl', 'devicemessage', 'devicetoast', 'addtousergroup', 'removefromusergroup', 'removeallusersfromusergroup', 'devicesharing', 'devicepower', 'indexagenterrorlog', 'agentdownload', 'report', 'grouptoast', 'groupmessage'];
19
+const possibleCommands = ['edituser', 'listusers', 'listusersessions', 'listdevicegroups', 'listdevices', 'listusersofdevicegroup', 'listevents', 'logintokens', 'serverinfo', 'userinfo', 'adduser', 'removeuser', 'adddevicegroup', 'removedevicegroup', 'editdevicegroup', 'broadcast', 'showevents', 'addusertodevicegroup', 'removeuserfromdevicegroup', 'addusertodevice', 'removeuserfromdevice', 'sendinviteemail', 'generateinvitelink', 'config', 'movetodevicegroup', 'deviceinfo', 'removedevice', 'editdevice', 'addlocaldevice', 'addamtdevice', 'addusergroup', 'listusergroups', 'removeusergroup', 'runcommand', 'shell', 'upload', 'download', 'deviceopenurl', 'devicemessage', 'devicetoast', 'addtousergroup', 'removefromusergroup', 'removeallusersfromusergroup', 'devicesharing', 'devicepower', 'indexagenterrorlog', 'agentdownload', 'report', 'grouptoast', 'groupmessage'];
20
if (args.proxy != null) { try { require('https-proxy-agent'); } catch (ex) { console.log('Missing module "https-proxy-agent", type "npm install https-proxy-agent" to install it.'); return; } }
21
22
if (args['_'].length == 0) {
@@ -36,6 +36,8 @@ if (args['_'].length == 0) {
36
console.log(" ListEvents - List server events.");
37
console.log(" LoginTokens - List, create and remove login tokens.");
38
console.log(" DeviceInfo - Show information about a device.");
39
+ console.log(" AddLocalDevice - Add a local device.");
40
+ console.log(" AddAmtDevice - Add a AMT device.");
41
console.log(" EditDevice - Make changes to a device.");
42
console.log(" RemoveDevice - Delete a device.");
43
console.log(" Config - Perform operation on config.json file.");
@@ -109,6 +111,22 @@ if (args['_'].length == 0) {
111
else { ok = true; }
112
break;
113
}
114
+ case 'addlocaldevice': {
115
+ if (args.id == null) { console.log(winRemoveSingleQuotes("Missing device id, use --id '[deviceid]'")); }
116
+ else if (args.devicename == null) { console.log(winRemoveSingleQuotes("Missing devicename, use --devicename [devicename]")); }
117
+ else if (args.hostname == null) { console.log(winRemoveSingleQuotes("Missing hostname, use --hostname [hostname]")); }
118
+ else { ok = true; }
119
+ break;
120
+ }
121
+ case 'addamtdevice': {
122
+ if (args.id == null) { console.log(winRemoveSingleQuotes("Missing device id, use --id '[deviceid]'")); }
123
+ else if (args.devicename == null) { console.log(winRemoveSingleQuotes("Missing devicename, use --devicename [devicename]")); }
124
+ else if (args.hostname == null) { console.log(winRemoveSingleQuotes("Missing hostname, use --hostname [hostname]")); }
125
+ else if (args.user == null) { console.log(winRemoveSingleQuotes("Missing user, use --user [user]")); }
126
+ else if (args.pass == null) { console.log(winRemoveSingleQuotes("Missing pass, use --pass [pass]")); }
127
+ else { ok = true; }
128
+ break;
129
+ }
130
case 'addusertodevicegroup': {
131
if ((args.id == null) && (args.group == null)) { console.log(winRemoveSingleQuotes("Device group identifier missing, use --id '[groupid]' or --group [groupname]")); }
132
else if (args.userid == null) { console.log("Add user to group missing useid, use --userid [userid]"); }
@@ -788,6 +806,55 @@ if (args['_'].length == 0) {
806
}
807
break;
808
}
809
+ case 'addlocaldevice': {
810
+ console.log("Add a Local Device, Example usages:\r\n");
811
+ console.log(winRemoveSingleQuotes(" MeshCtrl AddLocalDevice --id 'meshid' --devicename 'devicename' --hostname 'hostname'"));
812
+ console.log(winRemoveSingleQuotes(" MeshCtrl AddLocalDevice --id 'meshid' --devicename 'devicename' --hostname 'hostname' --type 6"));
813
+ console.log("\r\nRequired arguments:\r\n");
814
+ if (process.platform == 'win32') {
815
+ console.log(" --id [meshid] - The mesh identifier.");
816
+ console.log(" --devicename [devicename] - The device name.");
817
+ console.log(" --hostname [hostname] - The devices hostname or ip address.");
818
+ } else {
819
+ console.log(" --id '[meshid]' - The mesh identifier.");
820
+ console.log(" --devicename '[devicename]' - The device name.");
821
+ console.log(" --hostname '[hostname]' - The devices hostname or ip address.");
822
+ }
823
+
824
+ console.log("\r\nOptional arguments:\r\n");
825
+ console.log(" --type [TypeNumber] - With the following choices:");
826
+ console.log(" type 4 - Default, Windows (RDP)");
827
+ console.log(" type 6 - Linux (SSH/SCP/VNC)");
828
+ console.log(" type 29 - macOS (SSH/SCP/VNC)");
829
+ break;
830
+ }
831
+ case 'addamtdevice': {
832
+ console.log("Add an Intel AMT Device, Example usages:\r\n");
833
+ console.log(winRemoveSingleQuotes(" MeshCtrl AddAmtDevice --id 'meshid' --devicename 'devicename' --hostname 'hostname --user 'admin' --pass 'admin'"));
834
+ console.log(winRemoveSingleQuotes(" MeshCtrl AddAmtDevice --id 'meshid' --devicename 'devicename' --hostname 'hostname --user 'admin' --pass 'admin' --notls"));
835
+ console.log("\r\nRequired arguments:\r\n");
836
+ if (process.platform == 'win32') {
837
+ console.log(" --id [meshid] - The mesh identifier.");
838
+ console.log(" --devicename [devicename] - The device name.");
839
+ console.log(" --hostname [hostname] - The devices hostname or ip address.");
840
+ console.log(" --user [user] - The devices AMT username.");
841
+ console.log(" --pass [pass] - The devices AMT password.");
842
+ console.log("")
843
+ } else {
844
+ console.log(" --id '[meshid]' - The mesh identifier.");
845
+ console.log(" --devicename '[devicename]' - The device name.");
846
+ console.log(" --hostname '[hostname]' - The devices hostname or ip address.");
847
+ console.log(" --user '[user]' - The devices AMT username.");
848
+ console.log(" --pass '[pass]' - The devices AMT password.");
849
+ }
850
+ console.log("\r\nOptional arguments:\r\n");
851
+ if (process.platform == 'win32') {
852
+ console.log(" --notls - Use No TLS Security.");
853
+ } else {
854
+ console.log(" --notls - Use No TLS Security.");
855
+ }
856
+ break;
857
+ }
858
case 'editdevice': {
859
console.log("Change information about a device, Example usages:\r\n");
860
console.log(winRemoveSingleQuotes(" MeshCtrl EditDevice --id 'deviceid' --name 'device1'"));
@@ -1490,6 +1557,29 @@ function serverConnect() {
1557
ws.send(JSON.stringify(op));
1558
break;
1559
}
1560
+ case 'addamtdevice': {
1561
+ var op = { action: 'addamtdevice', amttls: 1, responseid: 'meshctrl' };
1562
+ if (args.id) { op.meshid = args.id; }
1563
+ if ((typeof args.devicename == 'string') && (args.devicename != '')) { op.devicename = args.devicename; }
1564
+ if ((typeof args.hostname == 'string') && (args.hostname != '')) { op.hostname = args.hostname; }
1565
+ if ((typeof args.user == 'string') && (args.user != '')) { op.amtusername = args.user; }
1566
+ if ((typeof args.pass == 'string') && (args.pass != '')) { op.amtpassword = args.pass; }
1567
+ if (args.notls) { op.amttls = 0; }
1568
+ ws.send(JSON.stringify(op));
1569
+ break;
1570
+ }
1571
+ case 'addlocaldevice': {
1572
+ var op = { action: 'addlocaldevice', type: 4, responseid: 'meshctrl' };
1573
+ if (args.id) { op.meshid = args.id; }
1574
+ if ((typeof args.devicename == 'string') && (args.devicename != '')) { op.devicename = args.devicename; }
1575
+ if ((typeof args.hostname == 'string') && (args.hostname != '')) { op.hostname = args.hostname; }
1576
+ if (args.type) {
1577
+ if ((typeof parseInt(args.type) != 'number') || isNaN(parseInt(args.type))) { console.log("Invalid type."); process.exit(1); return; }
1578
+ op.type = args.type;
1579
+ }
1580
+ ws.send(JSON.stringify(op));
1581
+ break;
1582
+ }
1583
case 'editdevicegroup': {
1584
var op = { action: 'editmesh', responseid: 'meshctrl' };
1585
if (args.id) { op.meshid = args.id; } else if (args.group) { op.meshidname = args.group; }
@@ -2084,6 +2174,8 @@ function serverConnect() {
2174
case 'toast': // TOAST
2175
case 'adduser': // ADDUSER
2176
case 'edituser': // EDITUSER
2177
+ case 'addamtdevice': // ADDAMTDEVICE
2178
+ case 'addlocaldevice': // ADDLOCALDEVICE
2179
case 'removedevices': // REMOVEDEVICE
2180
case 'changedevice': // EDITDEVICE
2181
case 'deleteuser': // REMOVEUSER
meshuser.js
+77
-56
@@ -2555,77 +2555,98 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
2555
}
2556
case 'addlocaldevice':
2557
{
2558
- if (common.validateString(command.meshid, 8, 134) == false) break; // Check meshid
2559
- if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
2560
- if (common.validateString(command.devicename, 1, 256) == false) break; // Check device name
2561
- if (common.validateString(command.hostname, 1, 256) == false) break; // Check hostname
2562
- if (typeof command.type != 'number') break; // Type must be a number
2563
- if ((command.type != 4) && (command.type != 6) && (command.type != 29)) break; // Check device type
2564
-
2565
- // Get the mesh
2566
- mesh = parent.meshes[command.meshid];
2567
- if (mesh) {
2568
- if (mesh.mtype != 3) return; // This operation is only allowed for mesh type 3, local device agentless mesh.
2569
-
2570
- // Check if this user has rights to do this
2571
- if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) return;
2572
-
2573
- // Create a new nodeid
2574
- parent.crypto.randomBytes(48, function (err, buf) {
2575
- // Create the new node
2576
- nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
2577
- var device = { type: 'node', _id: nodeid, meshid: command.meshid, mtype: 3, icon: 1, name: command.devicename, host: command.hostname, domain: domain.id, agent: { id: command.type, caps: 0 } };
2578
- db.Set(device);
2579
-
2580
- // Event the new node
2581
- parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(command.meshid, [nodeid]), obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msgid: 84, msgArgs: [command.devicename, mesh.name], msg: 'Added device ' + command.devicename + ' to device group ' + mesh.name, domain: domain.id });
2582
- });
2558
+ var err = null;
2559
+ // Perform input validation
2560
+ try {
2561
+ if (common.validateString(command.meshid, 8, 134) == false) { err = "Invalid device group id"; } // Check meshid
2562
+ if (common.validateString(command.devicename, 1, 256) == false) { err = "Invalid devicename"; } // Check device name
2563
+ if (common.validateString(command.hostname, 1, 256) == false) { err = "Invalid hostname"; } // Check hostname
2564
+ if (typeof command.type != 'number') { err = "Invalid type"; } // Type must be a number
2565
+ if ((command.type != 4) && (command.type != 6) && (command.type != 29)) { err = "Invalid type"; } // Check device type
2566
+ else {
2567
+ if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
2568
+ mesh = parent.meshes[command.meshid];
2569
+ if (mesh == null) { err = "Unknown device group"; }
2570
+ if (mesh.mtype != 3) { err = "Local device agentless mesh only allowed" } // This operation is only allowed for mesh type 3, local device agentless mesh.
2571
+ else if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) { err = "Permission denied"; }
2572
+ else if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) { err = "Invalid domain"; } // Invalid domain, operation only valid for current domain
2573
+ }
2574
+ } catch (ex) { console.log(ex); err = "Validation exception: " + ex; }
2575
+ // Handle any errors
2576
+ if (err != null) {
2577
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'changeDeviceMesh', responseid: command.responseid, result: err })); } catch (ex) { } }
2578
+ break;
2579
}
2580
2581
+ // Create a new nodeid
2582
+ parent.crypto.randomBytes(48, function (err, buf) {
2583
+ // Create the new node
2584
+ nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
2585
+ var device = { type: 'node', _id: nodeid, meshid: command.meshid, mtype: 3, icon: 1, name: command.devicename, host: command.hostname, domain: domain.id, agent: { id: command.type, caps: 0 } };
2586
+ db.Set(device);
2587
+
2588
+ // Event the new node
2589
+ parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(command.meshid, [nodeid]), obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msgid: 84, msgArgs: [command.devicename, mesh.name], msg: 'Added device ' + command.devicename + ' to device group ' + mesh.name, domain: domain.id });
2590
+ // Send response if required
2591
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addlocaldevice', responseid: command.responseid, result: 'ok' })); } catch (ex) { } }
2592
+ });
2593
break;
2594
}
2595
case 'addamtdevice':
2596
{
2597
if (args.wanonly == true) return; // This is a WAN-only server, local Intel AMT computers can't be added
2590
- if (common.validateString(command.meshid, 8, 134) == false) break; // Check meshid
2591
- if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) return; // Invalid domain, operation only valid for current domain
2592
- if (common.validateString(command.devicename, 1, 256) == false) break; // Check device name
2593
- if (common.validateString(command.hostname, 1, 256) == false) break; // Check hostname
2594
- if (common.validateString(command.amtusername, 0, 16) == false) break; // Check username
2595
- if (common.validateString(command.amtpassword, 0, 16) == false) break; // Check password
2596
- if (command.amttls == '0') { command.amttls = 0; } else if (command.amttls == '1') { command.amttls = 1; } // Check TLS flag
2597
- if ((command.amttls != 1) && (command.amttls != 0)) break;
2598
+ var err = null;
2599
+ // Perform input validation
2600
+ try {
2601
+ if (common.validateString(command.meshid, 8, 134) == false) { err = "Invalid device group id"; } // Check meshid
2602
+ if (common.validateString(command.devicename, 1, 256) == false) { err = "Invalid devicename"; } // Check device name
2603
+ if (common.validateString(command.hostname, 1, 256) == false) { err = "Invalid hostname"; } // Check hostname
2604
+ if (common.validateString(command.amtusername, 0, 16) == false) { err = "Invalid amtusername"; } // Check username
2605
+ if (common.validateString(command.amtpassword, 0, 16) == false) { err = "Invalid amtpassword"; } // Check password
2606
+ if (command.amttls == '0') { command.amttls = 0; } else if (command.amttls == '1') { command.amttls = 1; } // Check TLS flag
2607
+ if ((command.amttls != 1) && (command.amttls != 0)) { err = "Invalid amttls"; }
2608
+ else {
2609
+ if (command.meshid.indexOf('/') == -1) { command.meshid = 'mesh/' + domain.id + '/' + command.meshid; }
2610
+ // Get the mesh
2611
+ mesh = parent.meshes[command.meshid];
2612
+ if (mesh == null) { err = "Unknown device group"; }
2613
+ if (mesh.mtype != 1) { err = "Intel AMT agentless mesh only allowed"; } // This operation is only allowed for mesh type 1, Intel AMT agentless mesh.
2614
+ // Check if this user has rights to do this
2615
+ else if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) { err = "Permission denied"; }
2616
+ else if ((command.meshid.split('/').length != 3) || (command.meshid.split('/')[1] != domain.id)) { err = "Invalid domain"; } // Invalid domain, operation only valid for current domain
2617
+ }
2618
+ } catch (ex) { console.log(ex); err = "Validation exception: " + ex; }
2619
+
2620
+ // Handle any errors
2621
+ if (err != null) {
2622
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'changeDeviceMesh', responseid: command.responseid, result: err })); } catch (ex) { } }
2623
+ break;
2624
+ }
2625
2626
// If we are in WAN-only mode, hostname is not used
2627
if ((args.wanonly == true) && (command.hostname)) { delete command.hostname; }
2628
2602
- // Get the mesh
2603
- mesh = parent.meshes[command.meshid];
2604
- if (mesh) {
2605
- if (mesh.mtype != 1) return; // This operation is only allowed for mesh type 1, Intel AMT agentless mesh.
2606
-
2607
- // Check if this user has rights to do this
2608
- if ((parent.GetMeshRights(user, mesh) & MESHRIGHT_MANAGECOMPUTERS) == 0) return;
2629
+ // Create a new nodeid
2630
+ parent.crypto.randomBytes(48, function (err, buf) {
2631
+ // Create the new node
2632
+ nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
2633
+ var device = { type: 'node', _id: nodeid, meshid: command.meshid, mtype: 1, icon: 1, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: command.amttls } };
2634
2610
- // Create a new nodeid
2611
- parent.crypto.randomBytes(48, function (err, buf) {
2612
- // Create the new node
2613
- nodeid = 'node/' + domain.id + '/' + buf.toString('base64').replace(/\+/g, '@').replace(/\//g, '$');
2614
- var device = { type: 'node', _id: nodeid, meshid: command.meshid, mtype: 1, icon: 1, name: command.devicename, host: command.hostname, domain: domain.id, intelamt: { user: command.amtusername, pass: command.amtpassword, tls: command.amttls } };
2635
+ // Add optional feilds
2636
+ if (common.validateInt(command.state, 0, 3)) { device.intelamt.state = command.state; }
2637
+ if (common.validateString(command.ver, 1, 16)) { device.intelamt.ver = command.ver; }
2638
+ if (common.validateString(command.hash, 1, 256)) { device.intelamt.hash = command.hash; }
2639
+ if (common.validateString(command.realm, 1, 256)) { device.intelamt.realm = command.realm; }
2640
2616
- // Add optional feilds
2617
- if (common.validateInt(command.state, 0, 3)) { device.intelamt.state = command.state; }
2618
- if (common.validateString(command.ver, 1, 16)) { device.intelamt.ver = command.ver; }
2619
- if (common.validateString(command.hash, 1, 256)) { device.intelamt.hash = command.hash; }
2620
- if (common.validateString(command.realm, 1, 256)) { device.intelamt.realm = command.realm; }
2641
+ // Save the device to the database
2642
+ db.Set(device);
2643
2622
- // Save the device to the database
2623
- db.Set(device);
2644
+ // Event the new node
2645
+ parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(command.meshid, [nodeid]), obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msgid: 84, msgArgs: [command.devicename, mesh.name], msg: 'Added device ' + command.devicename + ' to device group ' + mesh.name, domain: domain.id });
2646
+ // Send response if required
2647
+ if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'addamtdevice', responseid: command.responseid, result: 'ok' })); } catch (ex) { } }
2648
+ });
2649
2625
- // Event the new node
2626
- parent.parent.DispatchEvent(parent.CreateMeshDispatchTargets(command.meshid, [nodeid]), obj, { etype: 'node', userid: user._id, username: user.name, action: 'addnode', node: parent.CloneSafeNode(device), msgid: 84, msgArgs: [command.devicename, mesh.name], msg: 'Added device ' + command.devicename + ' to device group ' + mesh.name, domain: domain.id });
2627
- });
2628
- }
2650
break;
2651
}
2652
case 'scanamtdevice':