From bd2e4f4d2bbbd32312b32fdde5580491fc3b3bfd Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Tue, 19 Oct 2021 11:47:39 -0700 Subject: [PATCH] Added session termination feature except for desktop multiplexor. --- agents/meshcore.js | 23 +++++++++++++++++++- meshuser.js | 23 ++++++++++++++++++++ views/default.handlebars | 46 ++++++++++++++++++++++++++++++++++------ 3 files changed, 85 insertions(+), 7 deletions(-) diff --git a/agents/meshcore.js b/agents/meshcore.js index 6e690def..8044af78 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1015,6 +1015,22 @@ function handleServerCommand(data) { } break; } + case 'endtunnel': { + // Terminate one or more tunnels + if ((data.rights != 4294967295) && (data.xuserid != data.userid)) return; // This command requires full admin rights on the device or user self-closes it's own sessions + for (var i in tunnels) { + if ((tunnels[i].userid == data.xuserid) && (tunnels[i].guestname == data.guestname)) { + var disconnect = false; + if ((data.protocol == 'kvm') && (tunnels[i].protocol == 2)) { disconnect = true; } + else if ((data.protocol == 'terminal') && (tunnels[i].protocol == 1)) { disconnect = true; } + else if ((data.protocol == 'files') && (tunnels[i].protocol == 5)) { disconnect = true; } + else if ((data.protocol == 'tcp') && (tunnels[i].tcpport != null)) { disconnect = true; } + else if ((data.protocol == 'udp') && (tunnels[i].udpport != null)) { disconnect = true; } + if (disconnect) { if (tunnels[i].s != null) { tunnels[i].s.end(); } else { tunnels[i].end(); } } + } + } + break; + } case 'messagebox': { // Display a message box if (data.title && data.msg) { @@ -3988,7 +4004,12 @@ function processConsoleCommand(cmd, args, rights, sessionid) { } case 'tunnels': { // Show the list of current tunnels response = ''; - for (var i in tunnels) { response += 'Tunnel #' + i + ', ' + tunnels[i].url + '\r\n'; } + for (var i in tunnels) { + response += 'Tunnel #' + i + ', ' + tunnels[i].protocol; //tunnels[i].url + if (tunnels[i].userid) { response += ', ' + tunnels[i].userid; } + if (tunnels[i].guestname) { response += '/' + tunnels[i].guestname; } + response += '\r\n' + } if (response == '') { response = 'No websocket sessions.'; } break; } diff --git a/meshuser.js b/meshuser.js index 96889455..4c772a05 100644 --- a/meshuser.js +++ b/meshuser.js @@ -5660,6 +5660,29 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use break; } + case 'endDesktopMultiplex': { + var err = null, xuser = null; + try { + if (command.xuserid.indexOf('/') < 0) { command.xuserid = 'user/' + domain.id + '/' + command.xuserid; } + if (common.validateString(command.nodeid, 1, 1024) == false) { err = 'Invalid device identifier'; } // Check the meshid + else if (command.nodeid.indexOf('/') == -1) { command.nodeid = 'node/' + domain.id + '/' + command.nodeid; } + const xusersplit = command.xuserid.split('/'); + xuser = parent.users[command.xuserid]; + if (xuser == null) { err = 'User does not exists'; } + else if ((obj.crossDomain !== true) && ((xusersplit.length != 3) || (xusersplit[1] != domain.id))) { err = 'Invalid domain'; } // Invalid domain, operation only valid for current domain + } catch (ex) { err = 'Validation exception: ' + ex; } + + // Handle any errors + if (err != null) { if (command.responseid != null) { try { ws.send(JSON.stringify({ action: 'changeusernotify', responseid: command.responseid, result: err })); } catch (ex) { } } break; } + + // Get the node and the rights for this node + parent.GetNodeWithRights(domain, xuser, command.nodeid, function (node, rights, visible) { + if ((rights != 0xFFFFFFFF) && (xuser._id != command.xuserid)) return; + //console.log('TODO'); + }); + + break; + } default: { // Unknown user action console.log('Unknown action from user ' + user.name + ': ' + command.action + '.'); diff --git a/views/default.handlebars b/views/default.handlebars index 814da103..dc254374 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -4461,28 +4461,62 @@ for (var i in node.sessions) { if ((i == 'kvm') && (node.sessions.multidesk == null)) { x += '' + "Remote Desktop" + ''; - for (var j in node.sessions.kvm) { x += addHtmlValue2(getUserName(j), (node.sessions.kvm[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.kvm[j]))); } + for (var j in node.sessions.kvm) { + var trash = ''; + if ((j == userinfo._id) || (GetNodeRights(node) == 0xFFFFFFFF)) { trash = ' '; } + x += addHtmlValue2(getUserName(j), ((node.sessions.kvm[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.kvm[j]))) + trash); + } } else if (i == 'multidesk') { x += '' + "Remote Desktop" + ''; - for (var j in node.sessions.multidesk) { x += addHtmlValue2(getUserName(j), ((node.sessions.multidesk[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.multidesk[j])))); } + for (var j in node.sessions.multidesk) { + var trash = ''; + if ((j == userinfo._id) || (GetNodeRights(node) == 0xFFFFFFFF)) { trash = ' '; } + x += addHtmlValue2(getUserName(j), ((node.sessions.multidesk[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.multidesk[j]))) + trash); + } } else if (i == 'terminal') { x += '' + "Terminal" + ''; - for (var j in node.sessions.terminal) { x += addHtmlValue2(getUserName(j), ((node.sessions.terminal[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.terminal[j])))); } + for (var j in node.sessions.terminal) { + var trash = ''; + if ((j == userinfo._id) || (GetNodeRights(node) == 0xFFFFFFFF)) { trash = ' '; } + x += addHtmlValue2(getUserName(j), ((node.sessions.terminal[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.terminal[j]))) + trash); + } } else if (i == 'files') { x += '' + "Files" + ''; - for (var j in node.sessions.files) { x += addHtmlValue2(getUserName(j), ((node.sessions.files[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.files[j])))); } + for (var j in node.sessions.files) { + var trash = ''; + if ((j == userinfo._id) || (GetNodeRights(node) == 0xFFFFFFFF)) { trash = ' '; } + x += addHtmlValue2(getUserName(j), ((node.sessions.files[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.files[j]))) + trash); + } } else if (i == 'tcp') { x += '' + "TCP Routing" + ''; - for (var j in node.sessions.tcp) { x += addHtmlValue2(getUserName(j), ((node.sessions.tcp[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.tcp[j])))); } + for (var j in node.sessions.tcp) { + var trash = ''; + if ((j == userinfo._id) || (GetNodeRights(node) == 0xFFFFFFFF)) { trash = ' '; } + x += addHtmlValue2(getUserName(j), ((node.sessions.tcp[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.tcp[j]))) + trash); + } } else if (i == 'udp') { x += '' + "UDP Routing" + ''; - for (var j in node.sessions.udp) { x += addHtmlValue2(getUserName(j), ((node.sessions.udp[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.udp[j])))); } + for (var j in node.sessions.udp) { + var trash = ''; + if ((j == userinfo._id) || (GetNodeRights(node) == 0xFFFFFFFF)) { trash = ' '; } + x += addHtmlValue2(getUserName(j), ((node.sessions.udp[j] == 1)?"1 session":nobreak(format("{0} sessions", node.sessions.udp[j]))) + trash); + } } } if (x != '') { setDialogMode(2, "Sessions" + ' - ' + EscapeHtml(node.name), 1, null, x, 'SESSIONS-' + node._id); } else { setDialogMode(0); } return false; } + function endDeviceSession(protocol, nodeid, userid) { + var userIdSplit = decodeURIComponent(userid).split('/'), uid = userIdSplit[0] + '/' + userIdSplit[1] + '/' + userIdSplit[2], guestname = null; + if ((userIdSplit.length == 4) && (userIdSplit[3].startsWith('guest:'))) { guestname = atob(userIdSplit[3].substring(6)); } + if (protocol == 'multidesk') { + meshserver.send({ action: 'endDesktopMultiplex', nodeid: decodeURIComponent(nodeid), xuserid: uid, guestname, guestname }); + } else { + meshserver.send({ action: 'msg', type: 'endtunnel', nodeid: decodeURIComponent(nodeid), xuserid: uid, guestname, guestname, protocol: protocol }); + } + } + // Show currently active sessions on this device function showDeviceMessages(nodeid, force, e) { if (e) haltEvent(e);