Web-SSH fixes and improvements.

Ylian Saint-Hilaire committed May 19, 2022 at 14:41 UTC 9c52cc4d8c0eaef25796e1da86cac6fae43fc64c
2 files changed +27 -18
apprelays.js
+12 -11
@@ -604,24 +604,24 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
604 parent.parent.db.Get(obj.cookie.nodeid, function (err, nodes) {
605 if ((err != null) || (nodes == null) || (nodes.length != 1)) return;
606 const node = nodes[0];
607 - if ((domain.allowsavingdevicecredentials === false) || (node.ssh == null) || (typeof node.ssh != 'object') || (node.ssh[user._id] == null) || (typeof node.ssh[user._id].u != 'string') || ((typeof node.ssh[user._id].p != 'string') && (typeof node.ssh[user._id].k != 'string'))) {
607 + if ((domain.allowsavingdevicecredentials === false) || (node.ssh == null) || (typeof node.ssh != 'object') || (node.ssh[obj.userid] == null) || (typeof node.ssh[obj.userid].u != 'string') || ((typeof node.ssh[obj.userid].p != 'string') && (typeof node.ssh[obj.userid].k != 'string'))) {
608 // Send a request for SSH authentication
609 try { ws.send(JSON.stringify({ action: 'sshauth' })) } catch (ex) { }
610 - } else if ((domain.allowsavingdevicecredentials !== false) && (node.ssh != null) && (typeof node.ssh[user._id].k == 'string') && (node.ssh[user._id].kp == null)) {
610 + } else if ((domain.allowsavingdevicecredentials !== false) && (node.ssh != null) && (typeof node.ssh[obj.userid].k == 'string') && (node.ssh[obj.userid].kp == null)) {
611 // Send a request for SSH authentication with option for only the private key password
612 - obj.username = node.ssh[user._id].u;
613 - obj.privateKey = node.ssh[user._id].k;
612 + obj.username = node.ssh[obj.userid].u;
613 + obj.privateKey = node.ssh[obj.userid].k;
614 try { ws.send(JSON.stringify({ action: 'sshauth', askkeypass: true })) } catch (ex) { }
615 } else {
616 // Use our existing credentials
617 obj.termSize = msg;
618 delete obj.keep;
619 - obj.username = node.ssh[user._id].u;
620 - if (typeof node.ssh[user._id].p == 'string') {
621 - obj.password = node.ssh[user._id].p;
622 - } else if (typeof node.ssh[user._id].k == 'string') {
623 - obj.privateKey = node.ssh[user._id].k;
624 - obj.privateKeyPass = node.ssh[user._id].kp;
619 + obj.username = node.ssh[obj.userid].u;
620 + if (typeof node.ssh[obj.userid].p == 'string') {
621 + obj.password = node.ssh[obj.userid].p;
622 + } else if (typeof node.ssh[obj.userid].k == 'string') {
623 + obj.privateKey = node.ssh[obj.userid].k;
624 + obj.privateKeyPass = node.ssh[obj.userid].kp;
625 }
626 startRelayConnection();
627 }
@@ -686,7 +686,8 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
686
687 // Decode the authentication cookie
688 obj.cookie = parent.parent.decodeCookie(req.query.auth, parent.parent.loginCookieEncryptionKey);
689 - if (obj.cookie == null) { obj.ws.send(JSON.stringify({ action: 'sessionerror' })); obj.close(); return; }
689 + if ((obj.cookie == null) || (obj.cookie.userid == null) || (parent.users[obj.cookie.userid] == null)) { obj.ws.send(JSON.stringify({ action: 'sessionerror' })); obj.close(); return; }
690 + obj.userid = obj.cookie.userid;
691
692 // Get the meshid for this device
693 parent.parent.db.Get(obj.cookie.nodeid, function (err, nodes) {
webserver.js
+15 -7
@@ -6842,7 +6842,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
6842 }
6843 });
6844 return;
6845 - } else if ((req.query.auth != null) && (req.query.auth != '')) {
6845 + }
6846 +
6847 + if ((req.query.auth != null) && (req.query.auth != '')) {
6848 // This is a encrypted cookie authentication
6849 var cookie = obj.parent.decodeCookie(req.query.auth, obj.parent.loginCookieEncryptionKey, 60); // Cookie with 1 hour timeout
6850 if ((cookie == null) && (obj.parent.multiServer != null)) { cookie = obj.parent.decodeCookie(req.query.auth, obj.parent.serverKey, 60); } // Try the server key
@@ -6853,20 +6855,26 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
6855 if ((cookie != null) && (cookie.userid != null) && (obj.users[cookie.userid]) && (cookie.domainid == domain.id) && (cookie.userid.split('/')[1] == domain.id)) {
6856 // Valid cookie, we are authenticated. Cookie of format { userid: 'user//name', domain: '' }
6857 func(ws, req, domain, obj.users[cookie.userid], cookie);
6858 + return;
6859 } else if ((cookie != null) && (cookie.a === 3) && (typeof cookie.u == 'string') && (obj.users[cookie.u]) && (cookie.u.split('/')[1] == domain.id)) {
6860 // Valid cookie, we are authenticated. Cookie of format { u: 'user//name', a: 3 }
6861 func(ws, req, domain, obj.users[cookie.u], cookie);
6862 + return;
6863 } else if ((cookie != null) && (cookie.nouser === 1)) {
6864 // This is a valid cookie, but no user. This is used for agent self-sharing.
6865 func(ws, req, domain, null, cookie);
6862 - } else {
6866 + return;
6867 + } /*else {
6868 // This is a bad cookie, keep going anyway, maybe we have a active session that will save us.
6869 if ((cookie != null) && (cookie.domainid != domain.id)) { parent.debug('web', 'ERR: Invalid domain, got \"' + cookie.domainid + '\", expected \"' + domain.id + '\".'); }
6870 parent.debug('web', 'ERR: Websocket bad cookie auth (Cookie:' + (cookie != null) + '): ' + req.query.auth);
6871 try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-2b' })); ws.close(); } catch (e) { }
6872 + return;
6873 }
6868 - return;
6869 - } else if (req.headers['x-meshauth'] != null) {
6874 + */
6875 + }
6876 +
6877 + if (req.headers['x-meshauth'] != null) {
6878 // This is authentication using a custom HTTP header
6879 var s = req.headers['x-meshauth'].split(',');
6880 for (var i in s) { s[i] = Buffer.from(s[i], 'base64').toString(); }
@@ -6954,13 +6962,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
6962 return;
6963 }
6964
6957 - //console.log(req.headers['x-meshauth']);
6958 -
6965 if (obj.args.user && obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]) {
6966 // A default user is active
6967 func(ws, req, domain, obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]);
6968 return;
6963 - } else if (req.session && (req.session.userid != null) && (req.session.userid.split('/')[1] == domain.id) && (obj.users[req.session.userid])) {
6969 + }
6970 +
6971 + if (req.session && (req.session.userid != null) && (req.session.userid.split('/')[1] == domain.id) && (obj.users[req.session.userid])) {
6972 // This user is logged in using the ExpressJS session
6973 func(ws, req, domain, obj.users[req.session.userid]);
6974 return;