From 4ac034420ea49734202ed5fad0bd2cb0b81c547f Mon Sep 17 00:00:00 2001
From: Ylian Saint-Hilaire
Date: Fri, 7 Aug 2020 15:51:28 -0700
Subject: [PATCH] Completed first version of desktop sharing.
---
meshrelay.js | 49 ++++++++++++++++++++++++---
meshuser.js | 4 +++
public/scripts/amt-wsman-0.2.0-min.js | 2 +-
views/default.handlebars | 6 ++--
4 files changed, 52 insertions(+), 9 deletions(-)
diff --git a/meshrelay.js b/meshrelay.js
index 14bd3f59..986241f5 100644
--- a/meshrelay.js
+++ b/meshrelay.js
@@ -14,7 +14,11 @@
"use strict";
module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie) {
- if (cookie && (cookie.nid != null)) { req.query.nodeid = cookie.nid; }
+ const currentTime = Date.now();
+ if (cookie) {
+ if ((typeof cookie.expire == 'number') && (cookie.expire <= currentTime)) { delete req.query.nodeid; }
+ else if (typeof cookie.nid == 'string') { req.query.nodeid = cookie.nid; }
+ }
var obj = {};
obj.ws = ws;
obj.id = req.query.id;
@@ -73,6 +77,7 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
delete obj.id;
delete obj.ws;
delete obj.peer;
+ delete obj.expireTimer;
};
obj.sendAgentMessage = function (command, userid, domainid) {
@@ -92,8 +97,8 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
mesh = parent.meshes[agent.dbMeshKey];
if ((rights != null) && (mesh != null) || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
if (ws.sessionId) { command.sessionid = ws.sessionId; } // Set the session id, required for responses.
- command.rights = rights.rights; // Add user rights flags to the message
- command.consent = mesh.consent; // Add user consent
+ command.rights = rights; // Add user rights flags to the message
+ if (typeof command.consent == 'number') { command.consent = command.consent | mesh.consent; } else { command.consent = mesh.consent; } // Add user consent
if (typeof domain.userconsentflags == 'number') { command.consent |= domain.userconsentflags; } // Add server required consent flags
command.username = user.name; // Add user name
command.realname = user.realname; // Add real name
@@ -111,8 +116,8 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
mesh = parent.meshes[routing.meshid];
if (rights != null || ((rights & 16) != 0)) { // TODO: 16 is console permission, may need more gradular permission checking
if (ws.sessionId) { command.fromSessionid = ws.sessionId; } // Set the session id, required for responses.
- command.rights = rights.rights; // Add user rights flags to the message
- command.consent = mesh.consent; // Add user consent
+ command.rights = rights; // Add user rights flags to the message
+ if (typeof command.consent == 'number') { command.consent = command.consent | mesh.consent; } else { command.consent = mesh.consent; } // Add user consent
if (typeof domain.userconsentflags == 'number') { command.consent |= domain.userconsentflags; } // Add server required consent flags
command.username = user.name; // Add user name
command.realname = user.realname; // Add real name
@@ -478,6 +483,9 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
} catch (ex) { console.log(ex); func(logfile, tag); }
}
+ // If this session has a expire time, setup the expire timer now.
+ if (cookie && (typeof cookie.expire == 'number')) { obj.expireTimer = setTimeout(obj.close, cookie.expire - currentTime); }
+
// Mark this relay session as authenticated if this is the user end.
obj.authenticated = (user != null);
if (obj.authenticated) {
@@ -562,6 +570,37 @@ module.exports.CreateMeshRelay = function (parent, ws, req, domain, user, cookie
performRelay();
});
return obj;
+ } else if ((cookie != null) && (cookie.nid != null) && (typeof cookie.r == 'number') && (typeof cookie.cf == 'number') && (typeof cookie.gn == 'string')) {
+ // We have routing instructions in the cookie, but first, check user access for this node.
+ parent.db.Get(cookie.nid, function (err, docs) {
+ if (docs.length == 0) { console.log('ERR: Node not found'); try { obj.close(); } catch (e) { } return; } // Disconnect websocket
+ const node = docs[0];
+
+ // Check if this user has permission to manage this computer
+ if ((parent.GetNodeRights(user, node.meshid, node._id) & MESHRIGHT_REMOTECONTROL) == 0) { console.log('ERR: Access denied (2)'); try { obj.close(); } catch (e) { } return; }
+
+ // Send connection request to agent
+ if (obj.id == null) { obj.id = ('' + Math.random()).substring(2); }
+ const rcookie = parent.parent.encodeCookie({ ruserid: user._id, nodeid: node._id }, parent.parent.loginCookieEncryptionKey);
+ const command = { nodeid: node._id, action: 'msg', type: 'tunnel', userid: user._id, value: '*/meshrelay.ashx?p=2&id=' + obj.id + '&rauth=' + rcookie + '&nodeid=' + node._id, soptions: {}, usage: 2, rights: cookie.r, guestname: cookie.gn, consent: cookie.cf, remoteaddr: cleanRemoteAddr(obj.req.clientIp) };
+ if (typeof domain.consentmessages == 'object') {
+ if (typeof domain.consentmessages.title == 'string') { command.soptions.consentTitle = domain.consentmessages.title; }
+ if (typeof domain.consentmessages.desktop == 'string') { command.soptions.consentMsgDesktop = domain.consentmessages.desktop; }
+ if (typeof domain.consentmessages.terminal == 'string') { command.soptions.consentMsgTerminal = domain.consentmessages.terminal; }
+ if (typeof domain.consentmessages.files == 'string') { command.soptions.consentMsgFiles = domain.consentmessages.files; }
+ }
+ if (typeof domain.notificationmessages == 'object') {
+ if (typeof domain.notificationmessages.title == 'string') { command.soptions.notifyTitle = domain.notificationmessages.title; }
+ if (typeof domain.notificationmessages.desktop == 'string') { command.soptions.notifyMsgDesktop = domain.notificationmessages.desktop; }
+ if (typeof domain.notificationmessages.terminal == 'string') { command.soptions.notifyMsgTerminal = domain.notificationmessages.terminal; }
+ if (typeof domain.notificationmessages.files == 'string') { command.soptions.notifyMsgFiles = domain.notificationmessages.files; }
+ }
+ parent.parent.debug('relay', 'Relay: Sending agent tunnel command: ' + JSON.stringify(command));
+ if (obj.sendAgentMessage(command, user._id, domain.id) == false) { delete obj.id; parent.parent.debug('relay', 'Relay: Unable to contact this agent (' + obj.req.clientIp + ')'); }
+
+ performRelay(0);
+ });
+ return obj;
}
}
diff --git a/meshuser.js b/meshuser.js
index d87684ce..4f5b2805 100644
--- a/meshuser.js
+++ b/meshuser.js
@@ -4389,8 +4389,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Get the device from the database
parent.GetNodeWithRights(domain, user, command.nodeid, function (node, rights, visible) {
+ // If node not found or we don't have remote control, reject.
if ((node == null) || ((rights & 8) == 0)) return;
+ // If there is MESHRIGHT_DESKLIMITEDINPUT or MESHRIGHT_REMOTEVIEWONLY on this account, reject this request.
+ if ((rights != 0xFFFFFFFF) && ((rights & 4352) != 0)) return;
+
// Create cookie
var expireTime = Date.now() + (60000 * command.expire);
const inviteCookie = parent.parent.encodeCookie({ a: 5, uid: user._id, gn: command.guestname, nid: node._id, cf: command.consent, expire: expireTime }, parent.parent.invitationLinkEncryptionKey);
diff --git a/public/scripts/amt-wsman-0.2.0-min.js b/public/scripts/amt-wsman-0.2.0-min.js
index 293387e7..389c6296 100644
--- a/public/scripts/amt-wsman-0.2.0-min.js
+++ b/public/scripts/amt-wsman-0.2.0-min.js
@@ -1 +1 @@
-var WsmanStackCreateService=function(e,s,r,a,o,t){var p={};function l(e){if(!e)return"";var s=" ";for(var r in e)e.hasOwnProperty(r)&&0===r.indexOf("@")&&(s+=r.substring(1)+'="'+e[r]+'" ');return s}function w(e){if(!e)return"";if("string"==typeof e)return e;if(e.InstanceID)return''+e.InstanceID+"";var s="";for(var r in e)if(e.hasOwnProperty(r)){if(s+='',e[r].ReferenceParameters){s+="",s+=""+e[r].Address+""+e[r].ReferenceParameters.ResourceURI+"";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o"+a[o].Value+"";else s+=""+a.Value+"";s+=""}else s+=e[r];s+=""}return s+=""}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,d,c){var m="",i="";null!=d&&null!=c&&(m="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken"+d+''+c+"",i=''),l=null!=l&&null!=l?""+l+"":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"+w(n)+m+''+r+""+i+"PT0.000000S";p.PerformAjax(u+"",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"+w(o)+"";p.PerformAjax(t+"",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60.000S"+w(t)+""+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+=""+s[o].Address+""+s[o].ReferenceParameters.ResourceURI+"";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n"+t[n].Value+"";else a+=""+t.Value+"";a+=""}else if(Array.isArray(s[o]))for(n=0;n"+s[o][n].toString()+"";else a+=""+s[o].toString()+"";return a+=""}(e,s);p.PerformAjax(n+"",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(t)+"';for(var d in s)l+=""+s[d]+"";p.PerformAjax(l+"",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60.000S'+s+"",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(s)+"";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S
'+r+"",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate"+p.Address+""+e+""+p.NextMessageId+++'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull"+p.Address+""+e+""+p.NextMessageId+++'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S'+s+"99999999",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o'+e.InstanceID+"";var s="";for(var r in e)if(e.hasOwnProperty(r)){if(s+='',e[r].ReferenceParameters){s+="",s+=""+e[r].Address+""+e[r].ReferenceParameters.ResourceURI+"";var a=e[r].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(a))for(var o=0;o"+a[o].Value+"";else s+=""+a.Value+"";s+=""}else s+=e[r];s+=""}return s+=""}return p.NextMessageId=1,p.Address="/wsman",p.comm=CreateWsmanComm(e,s,r,a,o,t),p.PerformAjax=function(e,o,s,r,a){null==a&&(a=""),p.comm.PerformAjax('"+e,function(e,s,r){if(200==s){var a=p.ParseWsman(e);a&&null!=a?o(p,a.Header.ResourceURI,a,200,r):o(p,null,{Header:{HttpError:s}},601,r)}else o(p,null,{Header:{HttpError:s}},s,r)},s,r)},p.CancelAllQueries=function(e){p.comm.CancelAllQueries(e)},p.GetNameFromUrl=function(e){var s=e.lastIndexOf("/");return-1==s?e:e.substring(s+1)},p.ExecSubscribe=function(e,s,r,a,o,t,n,l,c,d){var m="",i="";null!=c&&null!=d&&(m="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#UsernameToken"+c+''+d+"",i=''),l=null!=l&&null!=l?""+l+"":"";var u="http://schemas.xmlsoap.org/ws/2004/08/eventing/Subscribe"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"+w(n)+m+''+r+""+i+"PT0.000000S";p.PerformAjax(u+"",a,o,t,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing" xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust" xmlns:se="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:m="http://x.com"')},p.ExecUnSubscribe=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/08/eventing/Unsubscribe"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous"+w(o)+"";p.PerformAjax(t+"",s,r,a,'xmlns:e="http://schemas.xmlsoap.org/ws/2004/08/eventing"')},p.ExecPut=function(e,s,r,a,o,t){var n="http://schemas.xmlsoap.org/ws/2004/09/transfer/Put"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60.000S"+w(t)+""+function(e,s){if(!e||null==s)return"";var r=p.GetNameFromUrl(e),a="';for(var o in s)if(s.hasOwnProperty(o)&&0!==o.indexOf("__")&&0!==o.indexOf("@")&&void 0!==s[o]&&null!==s[o]&&"function"!=typeof s[o])if("object"==typeof s[o]&&s[o].ReferenceParameters){a+=""+s[o].Address+""+s[o].ReferenceParameters.ResourceURI+"";var t=s[o].ReferenceParameters.SelectorSet.Selector;if(Array.isArray(t))for(var n=0;n"+t[n].Value+"";else a+=""+t.Value+"";a+=""}else if(Array.isArray(s[o]))for(n=0;n"+s[o][n].toString()+"";else a+=""+s[o].toString()+"";return a+=""}(e,s);p.PerformAjax(n+"",r,a,o)},p.ExecCreate=function(e,s,r,a,o,t){var n=p.GetNameFromUrl(e),l="http://schemas.xmlsoap.org/ws/2004/09/transfer/Create"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(t)+"';for(var c in s)l+=""+s[c]+"";p.PerformAjax(l+"",r,a,o)},p.ExecCreateXml=function(e,s,r,a,o){var t=p.GetNameFromUrl(e);p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Create"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60.000S'+s+"",r,a,o)},p.ExecDelete=function(e,s,r,a,o){var t="http://schemas.xmlsoap.org/ws/2004/09/transfer/Delete"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S"+w(s)+"";p.PerformAjax(t,r,a,o)},p.ExecGet=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/transfer/Get"+p.Address+""+e+""+p.NextMessageId+++"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S'+r+"",a,o,t)},p.ExecEnum=function(e,s,r,a){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Enumerate"+p.Address+""+e+""+p.NextMessageId+++'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S',s,r,a)},p.ExecPull=function(e,s,r,a,o){p.PerformAjax("http://schemas.xmlsoap.org/ws/2004/09/enumeration/Pull"+p.Address+""+e+""+p.NextMessageId+++'http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymousPT60S'+s+"99999999",r,a,o)},p.ParseWsman=function(s){try{s.childNodes||(s=function(e){{if(window.DOMParser)return(new DOMParser).parseFromString(e,"text/xml");var s=new ActiveXObject("Microsoft.XMLDOM");return s.async=!1,s.loadXML(e),s}}(s));var e,r={Header:{}},a=s.getElementsByTagName("Header")[0];if(!(a=a||s.getElementsByTagName("a:Header")[0]))return null;for(var o=0;o';
if ((connectivity & 1) && (meshrights & 8)) { x += ''; }
//if ((connectivity & 1) && (meshrights & 8) && (node.agent.id < 5)) { x += ''; }
- if ((node.agent.caps & 1) && (connectivity & 1) && (meshrights & 8)) { x += ''; }
+ if ((node.agent.caps & 1) && (connectivity & 1) && (meshrights & 8) && ((meshrights == 0xFFFFFFFF) || ((meshrights & 4352) == 0))) { x += ''; }
// Custom UI
if ((customui != null) && (customui.devicebuttons != null)) {
@@ -5953,8 +5953,8 @@
showShareDeviceValidate();
}
- function showShareDeviceValidate() { QE('idx_dlgOkButton', Q('d2inviteName').value.length > 1); }
- function showShareDeviceEx() { meshserver.send({ action: 'createDeviceShareLink', nodeid: currentNode._id, guestname: Q('d2inviteName').value, expire: parseInt(Q('d2inviteExpire').value), consent: parseInt(Q('d2userConsent').value) }); }
+ function showShareDeviceValidate() { QE('idx_dlgOkButton', Q('d2inviteName').value.trim().length > 0); }
+ function showShareDeviceEx() { meshserver.send({ action: 'createDeviceShareLink', nodeid: currentNode._id, guestname: Q('d2inviteName').value.trim(), expire: parseInt(Q('d2inviteExpire').value), consent: parseInt(Q('d2userConsent').value) }); }
function deviceActionFunction() {
if (xxdialogMode) return;