Skip to content

Commit

Permalink
Fixed guest web relay session revocation (#4667)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ylianst committed Oct 25, 2022
1 parent 909f9f8 commit 41fb7d4
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 6 deletions.
2 changes: 1 addition & 1 deletion meshagent.js
Original file line number Diff line number Diff line change
Expand Up @@ -1842,7 +1842,7 @@ module.exports.CreateMeshAgent = function (parent, db, ws, req, args, domain) {
// Event device share removal
if (removedExact != null) {
// Send out an event that we removed a device share
var targets = parent.CreateNodeDispatchTargets(obj.dbMeshKey, obj.dbNodeKey, []);
var targets = parent.CreateNodeDispatchTargets(obj.dbMeshKey, obj.dbNodeKey, ['server-shareremove']);
var event = { etype: 'node', nodeid: obj.dbNodeKey, action: 'removedDeviceShare', msg: 'Removed Device Share', msgid: 102, msgArgs: ['Agent'], domain: domain.id, publicid: publicid };
parent.parent.DispatchEvent(targets, obj, event);
}
Expand Down
2 changes: 1 addition & 1 deletion meshuser.js
Original file line number Diff line number Diff line change
Expand Up @@ -4160,7 +4160,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
// Event device share removal
if (removedExact != null) {
// Send out an event that we removed a device share
var targets = parent.CreateNodeDispatchTargets(node.meshid, node._id, ['server-users', user._id]);
var targets = parent.CreateNodeDispatchTargets(node.meshid, node._id, ['server-users', 'server-shareremove', user._id]);
var event = { etype: 'node', userid: user._id, username: user.name, nodeid: node._id, action: 'removedDeviceShare', msg: 'Removed Device Share', msgid: 102, msgArgs: [removedExact.guestName], domain: domain.id, publicid: command.publicid };
parent.parent.DispatchEvent(targets, obj, event);

Expand Down
17 changes: 15 additions & 2 deletions webrelayserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,17 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates,
// If args.sessionkey is a string, use it as a single key, but args.sessionkey can also be used as an array of keys.
const keygrip = require('keygrip')((typeof args.sessionkey == 'string') ? [args.sessionkey] : args.sessionkey, 'sha384', 'base64');

// Watch for device share removal
parent.AddEventDispatch(['server-shareremove'], obj);
obj.HandleEvent = function (source, event, ids, id) {
if (event.action == 'removedDeviceShare') {
for (var relaySessionId in relaySessions) {
// A share was removed that matches an active session, close the session.
if (relaySessions[relaySessionId].xpublicid === event.publicid) { relaySessions[relaySessionId].close(); }
}
}
}

// Setup cookie session
const sessionOptions = {
name: 'xid', // Recommended security practice to not use the default cookie name
Expand Down Expand Up @@ -187,11 +198,11 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates,
if (req.query.c == null) { res.sendStatus(404); return; }

// Decode and check if this relay cookie is valid
var userid, domainid, domain, nodeid, addr, port, appid, webSessionId, expire;
var userid, domainid, domain, nodeid, addr, port, appid, webSessionId, expire, publicid;
const urlCookie = obj.parent.decodeCookie(req.query.c, parent.loginCookieEncryptionKey, 32); // Allow cookies up to 32 minutes old. The web page will renew this cookie every 30 minutes.
if (urlCookie == null) { res.sendStatus(404); return; }

// Decode the incomign cookie
// Decode the incoming cookie
if ((urlCookie.ruserid != null) && (urlCookie.x != null)) {
if (parent.webserver.destroyedSessions[urlCookie.ruserid + '/' + urlCookie.x] != null) { res.sendStatus(404); return; }

Expand Down Expand Up @@ -220,6 +231,7 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates,
port = urlCookie.port;
appid = (urlCookie.p == 16) ? 2 : 1; // appid: 1 = HTTP, 2 = HTTPS
webSessionId = userid + '/' + urlCookie.pid;
publicid = urlCookie.pid;
if (req.session.x) { delete req.session.x; } // Clear the web relay sessionid
if (req.session.userid) { delete req.session.userid; } // Clear the web relay userid
if (req.session.z != webSessionId) { req.session.z = webSessionId; } // Set the web relay guest session
Expand Down Expand Up @@ -248,6 +260,7 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates,

// Create a web relay session
const relaySession = require('./apprelays.js').CreateWebRelaySession(obj, db, req, args, domain, userid, nodeid, addr, port, appid, webSessionId, expire);
relaySession.xpublicid = publicid;
relaySession.onclose = function (sessionId) {
// Remove the relay session
delete relaySessions[sessionId];
Expand Down
17 changes: 15 additions & 2 deletions webserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,20 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF

// Web relay sessions
var webRelayNextSessionId = 1;
var webRelaySessions = {} // UserId/SessionId/Host --> Web Relay Session
var webRelaySessions = {} // UserId/SessionId/Host --> Web Relay Session
var webRelayCleanupTimer = null;

// Monitor web relay session removals
parent.AddEventDispatch(['server-shareremove'], obj);
obj.HandleEvent = function (source, event, ids, id) {
if (event.action == 'removedDeviceShare') {
for (var relaySessionId in webRelaySessions) {
// A share was removed that matches an active session, close the web relay session.
if (webRelaySessions[relaySessionId].xpublicid === event.publicid) { webRelaySessions[relaySessionId].close(); }
}
}
}

// Mesh Rights
const MESHRIGHT_EDITMESH = 0x00000001;
const MESHRIGHT_MANAGEUSERS = 0x00000002;
Expand Down Expand Up @@ -6749,7 +6760,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
if (req.query.c == null) { res.sendStatus(404); return; }

// Decode and check if this relay cookie is valid
var userid, domainid, domain, nodeid, addr, port, appid, webSessionId, expire;
var userid, domainid, domain, nodeid, addr, port, appid, webSessionId, expire, publicid;
const urlCookie = obj.parent.decodeCookie(req.query.c, parent.loginCookieEncryptionKey, 32); // Allow cookies up to 32 minutes old. The web page will renew this cookie every 30 minutes.
if (urlCookie == null) { res.sendStatus(404); return; }

Expand Down Expand Up @@ -6782,6 +6793,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
port = urlCookie.port;
appid = (urlCookie.p == 16) ? 2 : 1; // appid: 1 = HTTP, 2 = HTTPS
webSessionId = userid + '/' + urlCookie.pid;
publicid = urlCookie.pid;
if (req.session.x) { delete req.session.x; } // Clear the web relay sessionid
if (req.session.userid) { delete req.session.userid; } // Clear the web relay userid
if (req.session.z != webSessionId) { req.session.z = webSessionId; } // Set the web relay guest session
Expand Down Expand Up @@ -6854,6 +6866,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF

// Create a web relay session
const relaySession = require('./apprelays.js').CreateWebRelaySession(obj, db, req, args, domain, userid, nodeid, addr, port, appid, xrelaySessionId, expire);
relaySession.xpublicid = publicid;
relaySession.onclose = function (sessionId) {
// Remove the relay session
delete webRelaySessions[sessionId];
Expand Down

0 comments on commit 41fb7d4

Please sign in to comment.