From a80af24779e7c74a1c9bb0fd1a6dfd594105fe20 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 10 Sep 2021 21:17:39 -0700 Subject: [PATCH] Inter-user messaging fixes. --- meshbot.js | 117 ++++++++++++++++++++++++++++++++++++++++++++++++++++ meshuser.js | 4 +- 2 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 meshbot.js diff --git a/meshbot.js b/meshbot.js new file mode 100644 index 00000000..c1d5b68e --- /dev/null +++ b/meshbot.js @@ -0,0 +1,117 @@ +#!/usr/bin/env node + +// Make sure we have the dependency modules +try { require('minimist'); } catch (ex) { console.log('Missing module "minimist", type "npm install minimist" to install it.'); return; } +try { require('ws'); } catch (ex) { console.log('Missing module "ws", type "npm install ws" to install it.'); return; } + +var settings = {}; +const crypto = require('crypto'); +const args = require('minimist')(process.argv.slice(2)); +const path = require('path'); +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; } } + +if (args['_'].length == 0) { + console.log("MeshBot is a bot that connects to MeshCentral and perform various tasks."); + console.log("Information at: https://meshcentral.com"); + console.log("No action specified, use MeshBot like this:\r\n\r\n meshbot [action] [arguments]\r\n"); + console.log("Supported actions:"); + console.log(" run - Run the bot."); + console.log("\r\nSupported login arguments:"); + console.log(" --url [wss://server] - Server url, wss://localhost:443 is default."); + console.log(" - Use wss://localhost:443?key=xxx if login key is required."); + console.log(" --loginuser [username] - Login username, admin is default."); + console.log(" --loginpass [password] - Login password."); + console.log(" --token [number] - 2nd factor authentication token."); + console.log(" --loginkey [key] - Server login key."); + console.log(" --nocertcheck - Ignore server certificate warning."); + console.log(" --proxy [http://proxy:123] - Specify an HTTP proxy."); + return; +} else { + settings.cmd = args['_'][0].toLowerCase(); + if (settings.cmd != 'run') { console.log("Invalid command. \"run\" command will start the bot."); return; } else { serverConnect(); } +} + +function serverConnect() { + const WebSocket = require('ws'), options = {} + + // URL setup + var url = 'wss://localhost/control.ashx'; + if (args.url) { + url = args.url; + if (url.length < 5) { console.log("Invalid url."); process.exit(); return; } + if ((url.startsWith('wss://') == false) && (url.startsWith('ws://') == false)) { console.log("Invalid url."); process.exit(); return; } + var i = url.indexOf('?key='), loginKey = null; + if (i >= 0) { loginKey = url.substring(i + 5); url = url.substring(0, i); } + if (url.endsWith('/') == false) { url += '/'; } + url += 'control.ashx'; + if (loginKey != null) { url += '?key=' + loginKey; } + } + + // Certificate checking + if (args.nocertcheck) { options.rejectUnauthorized = false; } + + // Setup the HTTP proxy if needed + if (args.proxy != null) { + const HttpsProxyAgent = require('https-proxy-agent'); + options.agent = new HttpsProxyAgent(require('url').parse(args.proxy)); + } + + // Authentication setup + if (args.loginkey != null) { url += '?auth=' + args.loginkey; } // Cookie authentication + else if (args.loginpass != null) { // Password authentication + var username = 'admin'; + if (args.loginuser != null) { username = args.loginuser; } + var token = ''; + if (args.token != null) { token = ',' + Buffer.from('' + args.token).toString('base64'); } + options.headers = { 'x-meshauth': Buffer.from('' + username).toString('base64') + ',' + Buffer.from('' + args.loginpass).toString('base64') + token } + } + + // Connect to the server + const ws = new WebSocket(url, options); + console.log('MeshBot, press CTRl-C to stop.'); + console.log('Connecting to ' + url); + ws.on('open', function open() { + //console.log('Connected.'); + switch (settings.cmd) { + // ws.send(JSON.stringify({ action: 'users', responseid: 'meshctrl' })); // Ask for list of users + // ws.send(JSON.stringify({ action: 'meshes' })); // Ask for list of device groups + // ws.send(JSON.stringify({ action: 'nodes', responseid: 'meshctrl' })); // Ask for list of devices + } + }); + ws.on('close', function () { + console.log('Reconnecting in 10 seconds...'); + setTimeout(serverConnect, 10000); + }); + ws.on('error', function (err) { + if (err.code == 'ENOTFOUND') { console.log('Unable to resolve ' + url); } + else if (err.code == 'ECONNREFUSED') { console.log('Unable to connect to ' + url); } + else { console.log(err); } + }); + ws.on('message', function incoming(rawdata) { + var data = null; + try { data = JSON.parse(rawdata); } catch (ex) { } + if (data == null) { console.log('Unable to parse data: ' + rawdata); } + + //console.log("Got command: " + data.action); + + switch (data.action) { + case 'serverinfo': { console.log('Connected to server: ' + data.serverinfo.name); break; } + case 'userinfo': { + console.log('Connected at user: ' + data.userinfo.name); + if ((args.targetuser != null) || (args.targetsession != null)) { + console.log('Sending interuser message...'); + ws.send(JSON.stringify({ action: 'interuser', userid: args.targetuser, sessionid: args.targetsession, data: 'Hello!!!' })); // Send a hello message + } + break; + } + case 'interuser': { + console.log('Got InterUser Message', data); + if ((args.targetuser == null) && (args.targetsession == null) && (typeof data.data == 'string')) { // For testing, echo back the original message. + console.log('Sending interuser echo...'); + ws.send(JSON.stringify({ action: 'interuser', sessionid: data.sessionid, data: 'ECHO: ' + data.data })); + } + break; + } + } + }); +} diff --git a/meshuser.js b/meshuser.js index 0adb4a14..7fcc3810 100644 --- a/meshuser.js +++ b/meshuser.js @@ -622,8 +622,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } case 'interuser': { - // Sends data between users only if allowed. - if (command.data == null) return; + // Sends data between users only if allowed. Only a user in the "interUserMessaging": [] list, in the settings section of the config.json can receive and send inter-user messages from and to all users. + if ((parent.parent.config.settings.interusermessaging == null) || (parent.parent.config.settings.interusermessaging == false) || (command.data == null)) return; if (typeof command.sessionid == 'string') { var userSessionId = command.sessionid.split('/'); if (userSessionId.length != 4) return; command.userid = userSessionId[0] + '/' + userSessionId[1] + '/' + userSessionId[2]; } if (common.validateString(command.userid, 0, 2014) == false) return; var userSplit = command.userid.split('/');