| 1 | #!/usr/bin/env node |
| 2 | |
| 3 | /** |
| 4 | * @description MeshCentral bot sample code |
| 5 | * @author Ylian Saint-Hilaire |
| 6 | * @copyright Intel Corporation 2018-2022 |
| 7 | * @license Apache-2.0 |
| 8 | * @version v0.0.1 |
| 9 | */ |
| 10 | |
| 11 | // Make sure we have the dependency modules |
| 12 | try { require('minimist'); } catch (ex) { console.log('Missing module "minimist", type "npm install minimist" to install it.'); return; } |
| 13 | try { require('ws'); } catch (ex) { console.log('Missing module "ws", type "npm install ws" to install it.'); return; } |
| 14 | |
| 15 | var settings = {}; |
| 16 | const crypto = require('crypto'); |
| 17 | const args = require('minimist')(process.argv.slice(2)); |
| 18 | const path = require('path'); |
| 19 | 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; } } |
| 20 | |
| 21 | if (args['_'].length == 0) { |
| 22 | console.log("MeshBot is a bot that connects to MeshCentral and perform various tasks."); |
| 23 | console.log("Information at: https://meshcentral.com"); |
| 24 | console.log("No action specified, use MeshBot like this:\r\n\r\n meshbot [action] [arguments]\r\n"); |
| 25 | console.log("Supported actions:"); |
| 26 | console.log(" run - Run the bot."); |
| 27 | console.log("\r\nSupported login arguments:"); |
| 28 | console.log(" --url [wss://server] - Server url, wss://localhost:443 is default."); |
| 29 | console.log(" - Use wss://localhost:443?key=xxx if login key is required."); |
| 30 | console.log(" --loginuser [username] - Login username, admin is default."); |
| 31 | console.log(" --loginpass [password] - Login password."); |
| 32 | console.log(" --token [number] - 2nd factor authentication token."); |
| 33 | console.log(" --loginkey [key] - Server login key."); |
| 34 | console.log(" --nocertcheck - Ignore server certificate warning."); |
| 35 | console.log(" --proxy [http://proxy:123] - Specify an HTTP proxy."); |
| 36 | return; |
| 37 | } else { |
| 38 | settings.cmd = args['_'][0].toLowerCase(); |
| 39 | if (settings.cmd != 'run') { console.log("Invalid command. \"run\" command will start the bot."); return; } else { serverConnect(); } |
| 40 | } |
| 41 | |
| 42 | function serverConnect() { |
| 43 | const WebSocket = require('ws'), options = {} |
| 44 | |
| 45 | // URL setup |
| 46 | var url = 'wss://localhost/control.ashx'; |
| 47 | if (args.url) { |
| 48 | url = args.url; |
| 49 | if (url.length < 5) { console.log("Invalid url."); process.exit(); return; } |
| 50 | if ((url.startsWith('wss://') == false) && (url.startsWith('ws://') == false)) { console.log("Invalid url."); process.exit(); return; } |
| 51 | var i = url.indexOf('?key='), loginKey = null; |
| 52 | if (i >= 0) { loginKey = url.substring(i + 5); url = url.substring(0, i); } |
| 53 | if (url.endsWith('/') == false) { url += '/'; } |
| 54 | url += 'control.ashx'; |
| 55 | if (loginKey != null) { url += '?key=' + loginKey; } |
| 56 | } |
| 57 | |
| 58 | // Certificate checking |
| 59 | if (args.nocertcheck) { options.rejectUnauthorized = false; } |
| 60 | |
| 61 | // Setup the HTTP proxy if needed |
| 62 | if (args.proxy != null) { |
| 63 | const HttpsProxyAgent = require('https-proxy-agent'); |
| 64 | options.agent = new HttpsProxyAgent(new URL(args.proxy)); |
| 65 | } |
| 66 | |
| 67 | // Authentication setup |
| 68 | if (args.loginkey != null) { url += '?auth=' + args.loginkey; } // Cookie authentication |
| 69 | else if (args.loginpass != null) { // Password authentication |
| 70 | var username = 'admin'; |
| 71 | if (args.loginuser != null) { username = args.loginuser; } |
| 72 | var token = ''; |
| 73 | if (args.token != null) { token = ',' + Buffer.from('' + args.token).toString('base64'); } |
| 74 | options.headers = { 'x-meshauth': Buffer.from('' + username).toString('base64') + ',' + Buffer.from('' + args.loginpass).toString('base64') + token } |
| 75 | } |
| 76 | |
| 77 | // Connect to the server |
| 78 | const ws = new WebSocket(url, options); |
| 79 | console.log('MeshBot, press CTRl-C to stop.'); |
| 80 | console.log('Connecting to ' + url); |
| 81 | ws.on('open', function open() { |
| 82 | //console.log('Connected.'); |
| 83 | switch (settings.cmd) { |
| 84 | // ws.send(JSON.stringify({ action: 'users', responseid: 'meshctrl' })); // Ask for list of users |
| 85 | // ws.send(JSON.stringify({ action: 'meshes' })); // Ask for list of device groups |
| 86 | // ws.send(JSON.stringify({ action: 'nodes', responseid: 'meshctrl' })); // Ask for list of devices |
| 87 | } |
| 88 | }); |
| 89 | ws.on('close', function () { |
| 90 | console.log('Reconnecting in 10 seconds...'); |
| 91 | setTimeout(serverConnect, 10000); |
| 92 | }); |
| 93 | ws.on('error', function (err) { |
| 94 | if (err.code == 'ENOTFOUND') { console.log('Unable to resolve ' + url); } |
| 95 | else if (err.code == 'ECONNREFUSED') { console.log('Unable to connect to ' + url); } |
| 96 | else { console.log(err); } |
| 97 | }); |
| 98 | ws.on('message', function incoming(rawdata) { |
| 99 | var data = null; |
| 100 | try { data = JSON.parse(rawdata); } catch (ex) { } |
| 101 | if (data == null) { console.log('Unable to parse data: ' + rawdata); } |
| 102 | |
| 103 | //console.log("Got command: " + data.action); |
| 104 | |
| 105 | switch (data.action) { |
| 106 | case 'serverinfo': { console.log('Connected to server: ' + data.serverinfo.name); break; } |
| 107 | case 'userinfo': { |
| 108 | console.log('Connected at user: ' + data.userinfo.name); |
| 109 | if ((args.targetuser != null) || (args.targetsession != null)) { |
| 110 | console.log('Sending interuser message...'); |
| 111 | ws.send(JSON.stringify({ action: 'interuser', userid: args.targetuser, sessionid: args.targetsession, data: 'Hello!!!' })); // Send a hello message |
| 112 | } |
| 113 | break; |
| 114 | } |
| 115 | case 'interuser': { |
| 116 | console.log('Got InterUser Message', data); |
| 117 | if ((args.targetuser == null) && (args.targetsession == null) && (typeof data.data == 'string')) { // For testing, echo back the original message. |
| 118 | console.log('Sending interuser echo...'); |
| 119 | ws.send(JSON.stringify({ action: 'interuser', sessionid: data.sessionid, data: 'ECHO: ' + data.data })); |
| 120 | } |
| 121 | break; |
| 122 | } |
| 123 | } |
| 124 | }); |
| 125 | } |