Web-SSH fixes and improvements.

This commit is contained in:
Ylian Saint-Hilaire 2022-05-19 14:41:32 -07:00
parent f1f04bef98
commit 9c52cc4d8c
2 changed files with 27 additions and 18 deletions

View File

@ -604,24 +604,24 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
parent.parent.db.Get(obj.cookie.nodeid, function (err, nodes) { parent.parent.db.Get(obj.cookie.nodeid, function (err, nodes) {
if ((err != null) || (nodes == null) || (nodes.length != 1)) return; if ((err != null) || (nodes == null) || (nodes.length != 1)) return;
const node = nodes[0]; const node = nodes[0];
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'))) { 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'))) {
// Send a request for SSH authentication // Send a request for SSH authentication
try { ws.send(JSON.stringify({ action: 'sshauth' })) } catch (ex) { } try { ws.send(JSON.stringify({ action: 'sshauth' })) } catch (ex) { }
} else if ((domain.allowsavingdevicecredentials !== false) && (node.ssh != null) && (typeof node.ssh[user._id].k == 'string') && (node.ssh[user._id].kp == null)) { } else if ((domain.allowsavingdevicecredentials !== false) && (node.ssh != null) && (typeof node.ssh[obj.userid].k == 'string') && (node.ssh[obj.userid].kp == null)) {
// Send a request for SSH authentication with option for only the private key password // Send a request for SSH authentication with option for only the private key password
obj.username = node.ssh[user._id].u; obj.username = node.ssh[obj.userid].u;
obj.privateKey = node.ssh[user._id].k; obj.privateKey = node.ssh[obj.userid].k;
try { ws.send(JSON.stringify({ action: 'sshauth', askkeypass: true })) } catch (ex) { } try { ws.send(JSON.stringify({ action: 'sshauth', askkeypass: true })) } catch (ex) { }
} else { } else {
// Use our existing credentials // Use our existing credentials
obj.termSize = msg; obj.termSize = msg;
delete obj.keep; delete obj.keep;
obj.username = node.ssh[user._id].u; obj.username = node.ssh[obj.userid].u;
if (typeof node.ssh[user._id].p == 'string') { if (typeof node.ssh[obj.userid].p == 'string') {
obj.password = node.ssh[user._id].p; obj.password = node.ssh[obj.userid].p;
} else if (typeof node.ssh[user._id].k == 'string') { } else if (typeof node.ssh[obj.userid].k == 'string') {
obj.privateKey = node.ssh[user._id].k; obj.privateKey = node.ssh[obj.userid].k;
obj.privateKeyPass = node.ssh[user._id].kp; obj.privateKeyPass = node.ssh[obj.userid].kp;
} }
startRelayConnection(); startRelayConnection();
} }
@ -686,7 +686,8 @@ module.exports.CreateSshRelay = function (parent, db, ws, req, args, domain) {
// Decode the authentication cookie // Decode the authentication cookie
obj.cookie = parent.parent.decodeCookie(req.query.auth, parent.parent.loginCookieEncryptionKey); obj.cookie = parent.parent.decodeCookie(req.query.auth, parent.parent.loginCookieEncryptionKey);
if (obj.cookie == null) { obj.ws.send(JSON.stringify({ action: 'sessionerror' })); obj.close(); return; } if ((obj.cookie == null) || (obj.cookie.userid == null) || (parent.users[obj.cookie.userid] == null)) { obj.ws.send(JSON.stringify({ action: 'sessionerror' })); obj.close(); return; }
obj.userid = obj.cookie.userid;
// Get the meshid for this device // Get the meshid for this device
parent.parent.db.Get(obj.cookie.nodeid, function (err, nodes) { parent.parent.db.Get(obj.cookie.nodeid, function (err, nodes) {

View File

@ -6842,7 +6842,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates, doneF
} }
}); });
return; return;
} else if ((req.query.auth != null) && (req.query.auth != '')) { }
if ((req.query.auth != null) && (req.query.auth != '')) {
// This is a encrypted cookie authentication // This is a encrypted cookie authentication
var cookie = obj.parent.decodeCookie(req.query.auth, obj.parent.loginCookieEncryptionKey, 60); // Cookie with 1 hour timeout var cookie = obj.parent.decodeCookie(req.query.auth, obj.parent.loginCookieEncryptionKey, 60); // Cookie with 1 hour timeout
if ((cookie == null) && (obj.parent.multiServer != null)) { cookie = obj.parent.decodeCookie(req.query.auth, obj.parent.serverKey, 60); } // Try the server key 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
if ((cookie != null) && (cookie.userid != null) && (obj.users[cookie.userid]) && (cookie.domainid == domain.id) && (cookie.userid.split('/')[1] == domain.id)) { if ((cookie != null) && (cookie.userid != null) && (obj.users[cookie.userid]) && (cookie.domainid == domain.id) && (cookie.userid.split('/')[1] == domain.id)) {
// Valid cookie, we are authenticated. Cookie of format { userid: 'user//name', domain: '' } // Valid cookie, we are authenticated. Cookie of format { userid: 'user//name', domain: '' }
func(ws, req, domain, obj.users[cookie.userid], cookie); func(ws, req, domain, obj.users[cookie.userid], cookie);
return;
} else if ((cookie != null) && (cookie.a === 3) && (typeof cookie.u == 'string') && (obj.users[cookie.u]) && (cookie.u.split('/')[1] == domain.id)) { } else if ((cookie != null) && (cookie.a === 3) && (typeof cookie.u == 'string') && (obj.users[cookie.u]) && (cookie.u.split('/')[1] == domain.id)) {
// Valid cookie, we are authenticated. Cookie of format { u: 'user//name', a: 3 } // Valid cookie, we are authenticated. Cookie of format { u: 'user//name', a: 3 }
func(ws, req, domain, obj.users[cookie.u], cookie); func(ws, req, domain, obj.users[cookie.u], cookie);
return;
} else if ((cookie != null) && (cookie.nouser === 1)) { } else if ((cookie != null) && (cookie.nouser === 1)) {
// This is a valid cookie, but no user. This is used for agent self-sharing. // This is a valid cookie, but no user. This is used for agent self-sharing.
func(ws, req, domain, null, cookie); func(ws, req, domain, null, cookie);
} else { return;
} /*else {
// This is a bad cookie, keep going anyway, maybe we have a active session that will save us. // This is a bad cookie, keep going anyway, maybe we have a active session that will save us.
if ((cookie != null) && (cookie.domainid != domain.id)) { parent.debug('web', 'ERR: Invalid domain, got \"' + cookie.domainid + '\", expected \"' + domain.id + '\".'); } if ((cookie != null) && (cookie.domainid != domain.id)) { parent.debug('web', 'ERR: Invalid domain, got \"' + cookie.domainid + '\", expected \"' + domain.id + '\".'); }
parent.debug('web', 'ERR: Websocket bad cookie auth (Cookie:' + (cookie != null) + '): ' + req.query.auth); parent.debug('web', 'ERR: Websocket bad cookie auth (Cookie:' + (cookie != null) + '): ' + req.query.auth);
try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-2b' })); ws.close(); } catch (e) { } try { ws.send(JSON.stringify({ action: 'close', cause: 'noauth', msg: 'noauth-2b' })); ws.close(); } catch (e) { }
return;
} }
return; */
} else if (req.headers['x-meshauth'] != null) { }
if (req.headers['x-meshauth'] != null) {
// This is authentication using a custom HTTP header // This is authentication using a custom HTTP header
var s = req.headers['x-meshauth'].split(','); var s = req.headers['x-meshauth'].split(',');
for (var i in s) { s[i] = Buffer.from(s[i], 'base64').toString(); } 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
return; return;
} }
//console.log(req.headers['x-meshauth']);
if (obj.args.user && obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]) { if (obj.args.user && obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]) {
// A default user is active // A default user is active
func(ws, req, domain, obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]); func(ws, req, domain, obj.users['user/' + domain.id + '/' + obj.args.user.toLowerCase()]);
return; return;
} else if (req.session && (req.session.userid != null) && (req.session.userid.split('/')[1] == domain.id) && (obj.users[req.session.userid])) { }
if (req.session && (req.session.userid != null) && (req.session.userid.split('/')[1] == domain.id) && (obj.users[req.session.userid])) {
// This user is logged in using the ExpressJS session // This user is logged in using the ExpressJS session
func(ws, req, domain, obj.users[req.session.userid]); func(ws, req, domain, obj.users[req.session.userid]);
return; return;