From bd9739e1067f01d8bb34692f7ae61b3d5bb0f748 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Sat, 9 Jul 2022 13:32:55 -0700 Subject: [PATCH] Changed the web relay system to correctly with multiple DNS names, #4242 --- meshuser.js | 2 +- views/default.handlebars | 2 +- webrelayserver.js | 17 +++++++++++++---- webserver.js | 21 +++++++++++++++------ 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/meshuser.js b/meshuser.js index aa2fe965..ac0248dd 100644 --- a/meshuser.js +++ b/meshuser.js @@ -5635,7 +5635,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use ws.send(JSON.stringify({ action: 'authcookie', cookie: parent.parent.encodeCookie({ userid: user._id, domainid: domain.id, ip: req.clientIp }, parent.parent.loginCookieEncryptionKey), - rcookie: parent.parent.encodeCookie({ ruserid: user._id }, parent.parent.loginCookieEncryptionKey) + rcookie: parent.parent.encodeCookie({ ruserid: user._id, x: req.session.x }, parent.parent.loginCookieEncryptionKey) })); } catch (ex) { } } diff --git a/views/default.handlebars b/views/default.handlebars index b0a7c51f..28d29a73 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -8119,7 +8119,7 @@ var servername = serverinfo.name; if ((servername.indexOf('.') == -1) || ((features & 2) != 0)) { servername = window.location.hostname; } // If the server name is not set or it's in LAN-only mode, use the URL hostname as server name. if (webRelayDns != '') { servername = webRelayDns; } - var url = 'https://' + servername + ':' + webRelayPort + '/control-redirect.ashx?n=' + nodeid + '&p=' + port + '&appid=' + protocol; // Protocol: 1 = HTTP, 2 = HTTPS + var url = 'https://' + servername + ':' + webRelayPort + '/control-redirect.ashx?n=' + nodeid + '&p=' + port + '&appid=' + protocol + '&c=' + authRelayCookie; // Protocol: 1 = HTTP, 2 = HTTPS if (addr != null) { url += '&addr=' + addr; } if (relayid != null) { url += '&relayid=' + relayid; } safeNewWindow(url, 'WebRelay'); diff --git a/webrelayserver.js b/webrelayserver.js index f4b1d280..1415319c 100644 --- a/webrelayserver.js +++ b/webrelayserver.js @@ -120,7 +120,7 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates, return next(); } else { // If this is a normal request (GET, POST, etc) handle it here - if ((req.session.userid != null) && (req.session.x != null)) { + if ((req.session.userid != null) && (req.session.x != null) && (parent.webserver.destroyedSessions[req.session.userid + '/' + req.session.x] == null)) { var relaySession = relaySessions[req.session.userid + '/' + req.session.x]; if (relaySession != null) { // The web relay session is valid, use it @@ -153,7 +153,7 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates, // Handle incoming web socket calls obj.app.ws('/*', function (ws, req) { - if ((req.session.userid != null) && (req.session.x != null)) { + if ((req.session.userid != null) && (req.session.x != null) && (parent.webserver.destroyedSessions[req.session.userid + '/' + req.session.x] == null)) { var relaySession = relaySessions[req.session.userid + '/' + req.session.x]; if (relaySession != null) { // The multi-tunnel session is valid, use it @@ -170,12 +170,21 @@ module.exports.CreateWebRelayServer = function (parent, db, args, certificates, // This is the magic URL that will setup the relay session obj.app.get('/control-redirect.ashx', function (req, res) { - if ((req.session == null) || (req.session.userid == null)) { res.redirect('/'); return; } res.set({ 'Cache-Control': 'no-store' }); parent.debug('webrelay', 'webRelaySetup'); + // Decode the relay cookie + if (req.query.c != null) { + // Decode and check if this relay cookie is valid + const urlCookie = obj.parent.decodeCookie(req.query.c, parent.loginCookieEncryptionKey); + if ((urlCookie != null) && (urlCookie.ruserid != null) && (urlCookie.x != null) && (parent.webserver.destroyedSessions[urlCookie.ruserid + '/' + urlCookie.x] == null)) { + if (req.session.x != urlCookie.x) { req.session.x = urlCookie.x; } // Set the sessionid if missing + if (req.session.userid != urlCookie.ruserid) { req.session.userid = urlCookie.ruserid; } // Set the session userid if missing + } + } + // Check that all the required arguments are present - if ((req.session.userid == null) || (req.session.x == null) || (req.query.n == null) || (req.query.p == null) || ((req.query.appid != 1) && (req.query.appid != 2))) { res.redirect('/'); return; } + if ((req.session.userid == null) || (req.session.x == null) || (req.query.n == null) || (req.query.p == null) || (parent.webserver.destroyedSessions[req.session.userid + '/' + req.session.x] != null) || ((req.query.appid != 1) && (req.query.appid != 2))) { res.redirect('/'); return; } // Get the user and domain information const userid = req.session.userid; diff --git a/webserver.js b/webserver.js index 1de9992b..cbdca7fa 100644 --- a/webserver.js +++ b/webserver.js @@ -84,7 +84,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF obj.blockedAgents = 0; obj.renderPages = null; obj.renderLanguages = []; - obj.destroyedSessions = {}; + obj.destroyedSessions = {}; // userid/req.session.x --> destroyed session time // Web relay sessions var webRelayNextSessionId = 1; @@ -2799,7 +2799,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF // Create a authentication cookie const authCookie = obj.parent.encodeCookie({ userid: dbGetFunc.user._id, domainid: domain.id, ip: req.clientIp }, obj.parent.loginCookieEncryptionKey); - const authRelayCookie = obj.parent.encodeCookie({ ruserid: dbGetFunc.user._id, domainid: domain.id }, obj.parent.loginCookieEncryptionKey); + const authRelayCookie = obj.parent.encodeCookie({ ruserid: dbGetFunc.user._id, x: req.session.x }, obj.parent.loginCookieEncryptionKey); // Send the main web application var extras = (dbGetFunc.req.query.key != null) ? ('&key=' + dbGetFunc.req.query.key) : ''; @@ -6587,12 +6587,21 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF obj.webRelayRouter.get('/control-redirect.ashx', function (req, res, next) { if (req.headers.host != obj.args.relaydns) { res.sendStatus(404); return; } if ((req.session.userid == null) && obj.args.user && obj.users['user//' + obj.args.user.toLowerCase()]) { req.session.userid = 'user//' + obj.args.user.toLowerCase(); } // Use a default user if needed - if ((req.session == null) || (req.session.userid == null)) { res.redirect('/'); return; } res.set({ 'Cache-Control': 'no-store' }); parent.debug('web', 'webRelaySetup'); + // Decode the relay cookie + if (req.query.c != null) { + // Decode and check if this relay cookie is valid + const urlCookie = obj.parent.decodeCookie(req.query.c, obj.parent.loginCookieEncryptionKey); + if ((urlCookie != null) && (urlCookie.ruserid != null) && (urlCookie.x != null)) { + if (req.session.x != urlCookie.x) { req.session.x = urlCookie.x; } // Set the sessionid if missing + if (req.session.userid != urlCookie.ruserid) { req.session.userid = urlCookie.ruserid; } // Set the session userid if missing + } + } + // Check that all the required arguments are present - if ((req.session.userid == null) || (req.session.x == null) || (req.query.n == null) || (req.query.p == null) || ((req.query.appid != 1) && (req.query.appid != 2))) { res.redirect('/'); return; } + if ((req.session.userid == null) || (req.session.x == null) || (req.query.n == null) || (req.query.p == null) || ((obj.destroyedSessions[req.session.userid + '/' + req.session.x] != null)) || ((req.query.appid != 1) && (req.query.appid != 2))) { res.redirect('/'); return; } // Get the user and domain information const userid = req.session.userid; @@ -6691,7 +6700,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF // Handle an incoming request as a web relay function handleWebRelayRequest(req, res) { - if ((req.session.userid != null) && (req.session.x != null)) { + if ((req.session.userid != null) && (req.session.x != null) && (obj.destroyedSessions[req.session.userid + '/' + req.session.x] == null)) { var relaySession = webRelaySessions[req.session.userid + '/' + req.session.x]; if (relaySession != null) { // The web relay session is valid, use it @@ -6708,7 +6717,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF // Handle an incoming websocket connection as a web relay function handleWebRelayWebSocket(ws, req) { - if ((req.session.userid != null) && (req.session.x != null)) { + if ((req.session.userid != null) && (req.session.x != null) && (obj.destroyedSessions[req.session.userid + '/' + req.session.x] == null)) { var relaySession = webRelaySessions[req.session.userid + '/' + req.session.x]; if (relaySession != null) { // The multi-tunnel session is valid, use it