mirror of
https://github.com/Ylianst/MeshCentral.git
synced 2024-09-11 08:55:32 +03:00
Completed login token support.
This commit is contained in:
parent
6c3e010ce9
commit
8ce24152f4
102
meshuser.js
102
meshuser.js
@ -95,6 +95,13 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
const Wsman = require('./amt/amt-wsman.js');
|
||||
const Amt = require('./amt/amt.js');
|
||||
|
||||
// If this session has an expire time, setup a timer now.
|
||||
if ((req.session != null) && (typeof req.session.expire == 'number')) {
|
||||
var delta = (req.session.expire - Date.now());
|
||||
if (delta <= 0) { req.session = {}; try { ws.close(); } catch (ex) { } return; } // Session is already expired, close now.
|
||||
obj.expireTimer = setTimeout(function () { for (var i in req.session) { delete req.session[i]; } obj.close(); }, delta);
|
||||
}
|
||||
|
||||
// Send a message to the user
|
||||
//obj.send = function (data) { try { if (typeof data == 'string') { ws.send(Buffer.from(data, 'binary')); } else { ws.send(data); } } catch (e) { } }
|
||||
|
||||
@ -118,6 +125,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
if (obj.pingtimer) { clearInterval(obj.pingtimer); delete obj.pingtimer; }
|
||||
if (obj.pongtimer) { clearInterval(obj.pongtimer); delete obj.pongtimer; }
|
||||
|
||||
// Clear expire timeout
|
||||
if (obj.expireTimer != null) { clearTimeout(obj.expireTimer); delete obj.expireTimer; }
|
||||
|
||||
// Perform cleanup
|
||||
parent.parent.RemoveAllEventDispatch(ws);
|
||||
if (obj.serverStatsTimer != null) { clearInterval(obj.serverStatsTimer); delete obj.serverStatsTimer; }
|
||||
@ -340,6 +350,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
// Handle events
|
||||
ws.HandleEvent = function (source, event, ids, id) {
|
||||
// If this session is logged in using a loginToken and the token is removed, disconnect.
|
||||
if ((req.session.loginToken != null) && (typeof event == 'object') && (event.action == 'loginTokenChanged') && (event.removed != null) && (event.removed.indexOf(req.session.loginToken) >= 0)) { delete req.session; obj.close(); return; }
|
||||
|
||||
// Normally, only allow this user to receive messages from it's own domain.
|
||||
// If the user is a cross domain administrator, allow some select messages from different domains.
|
||||
if ((event.domain == null) || (event.domain == domain.id) || ((obj.crossDomain === true) && (allowedCrossDomainMessages.indexOf(event.action) >= 0))) {
|
||||
@ -874,6 +887,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'serverconsole':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// This is a server console message, only process this if full administrator
|
||||
if (user.siteadmin != SITERIGHT_ADMIN) break;
|
||||
|
||||
@ -1573,6 +1589,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'changelang':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// If this account is settings locked, return here.
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return;
|
||||
|
||||
@ -1599,6 +1618,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'changeemail':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// If the email is the username, this command is not allowed.
|
||||
if (domain.usernameisemail) return;
|
||||
|
||||
@ -1650,6 +1672,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'verifyemail':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// If this account is settings locked, return here.
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return;
|
||||
|
||||
@ -1795,6 +1820,11 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
db.Remove('ntp' + deluser._id); // Remove personal notes for this user
|
||||
db.Remove('im' + deluser._id); // Remove image for this user
|
||||
|
||||
// Delete any login tokens
|
||||
parent.parent.db.GetAllTypeNodeFiltered(['logintoken-' + deluser._id], domain.id, 'logintoken', null, function (err, docs) {
|
||||
if ((err == null) && (docs != null)) { for (var i = 0; i < docs.length; i++) { parent.parent.db.Remove(docs[i]._id, function () { }); } }
|
||||
});
|
||||
|
||||
// Delete all files on the server for this account
|
||||
try {
|
||||
var deluserpath = parent.getServerRootFilePath(deluser);
|
||||
@ -2209,6 +2239,8 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'updateUserImage':
|
||||
{
|
||||
if (req.session.loginToken != null) break; // Do not allow this command when logged in using a login token
|
||||
|
||||
var uid = user._id;
|
||||
if ((typeof command.userid == 'string') && ((user.siteadmin & SITERIGHT_MANAGEUSERS) != 0)) { uid = command.userid; }
|
||||
|
||||
@ -2653,6 +2685,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'changepassword':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// If this account is settings locked, return here.
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return;
|
||||
|
||||
@ -2878,6 +2913,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'serverversion':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// Check the server version
|
||||
if ((user.siteadmin & 16) == 0) break;
|
||||
if ((domain.myserver === false) || ((domain.myserver != null) && (domain.myserver !== true) && (domain.myserver.upgrade !== true))) break;
|
||||
@ -2887,6 +2925,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'serverupdate':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// Perform server update
|
||||
if ((user.siteadmin & 16) == 0) break;
|
||||
if ((domain.myserver === false) || ((domain.myserver != null) && (domain.myserver !== true) && (domain.myserver.upgrade !== true))) break;
|
||||
@ -4357,6 +4398,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otpemail':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
|
||||
// Check input
|
||||
@ -4381,6 +4425,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otpauth-request':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
|
||||
// Check if 2-step login is supported
|
||||
@ -4400,6 +4447,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otpauth-setup':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
|
||||
// Check if 2-step login is supported
|
||||
@ -4430,6 +4480,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otpauth-clear':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
|
||||
// Check if 2-step login is supported
|
||||
@ -4455,6 +4508,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otpauth-getpasswords':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// Check if 2-step login is supported
|
||||
const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true));
|
||||
if (twoStepLoginSupported == false) break;
|
||||
@ -4500,6 +4556,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otp-hkey-get':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// Check if 2-step login is supported
|
||||
const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true));
|
||||
if (twoStepLoginSupported == false) break;
|
||||
@ -4513,6 +4572,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otp-hkey-remove':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
|
||||
// Check if 2-step login is supported
|
||||
@ -4537,6 +4599,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otp-hkey-yubikey-add':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
|
||||
// Yubico API id and signature key can be requested from https://upgrade.yubico.com/getapikey/
|
||||
@ -4592,6 +4657,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otpdev-clear':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// Remove the authentication push notification device
|
||||
if (user.otpdev != null) {
|
||||
// Change the user
|
||||
@ -4609,6 +4677,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'otpdev-set':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// Attempt to add a authentication push notification device
|
||||
// This will only send a push notification to the device, the device needs to confirm for the auth device to be added.
|
||||
if (common.validateString(command.nodeid, 1, 1024) == false) break; // Check nodeid
|
||||
@ -4635,6 +4706,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'webauthn-startregister':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
|
||||
// Check if 2-step login is supported
|
||||
@ -4649,6 +4723,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
}
|
||||
case 'webauthn-endregister':
|
||||
{
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
const twoStepLoginSupported = ((parent.parent.config.settings.no2factorauth !== true) && (domain.auth != 'sspi') && (parent.parent.certificates.CommonName.indexOf('.') != -1) && (args.nousers !== true));
|
||||
if ((twoStepLoginSupported == false) || (obj.webAuthnReqistrationRequest == null)) return;
|
||||
@ -4689,6 +4766,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'verifyPhone': {
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
if (parent.parent.smsserver == null) return;
|
||||
if (common.validateString(command.phone, 1, 18) == false) break; // Check phone length
|
||||
@ -4702,6 +4782,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'confirmPhone': {
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
if ((parent.parent.smsserver == null) || (typeof command.cookie != 'string') || (typeof command.code != 'string') || (obj.failedSmsCookieCheck == 1)) break; // Input checks
|
||||
var cookie = parent.parent.decodeCookie(command.cookie);
|
||||
@ -4729,6 +4812,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'removePhone': {
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 1024) != 0)) return; // If this account is settings locked, return here.
|
||||
if (user.phone == null) break;
|
||||
|
||||
@ -5381,6 +5467,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'serverBackup': {
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
if ((user.siteadmin != SITERIGHT_ADMIN) || (typeof parent.parent.config.settings.autobackup.googledrive != 'object')) return;
|
||||
if (command.service == 'googleDrive') {
|
||||
if (command.state == 0) {
|
||||
@ -5403,6 +5492,9 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'twoFactorCookie': {
|
||||
// Do not allow this command when logged in using a login token
|
||||
if (req.session.loginToken != null) break;
|
||||
|
||||
// Generate a two-factor cookie
|
||||
if (((domain.twofactorcookiedurationdays == null) || (domain.twofactorcookiedurationdays > 0))) {
|
||||
var maxCookieAge = domain.twofactorcookiedurationdays;
|
||||
@ -5611,6 +5703,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
break;
|
||||
}
|
||||
case 'loginTokens': { // Respond with the list of currently valid login tokens
|
||||
if (req.session.loginToken != null) break; // Do not allow this command when logged in using a login token
|
||||
if ((typeof domain.passwordrequirements != 'object') && (domain.passwordrequirements.logintokens == false)) break; // Login tokens are not supported on this server
|
||||
|
||||
// If remove is an array or strings, we are going to be removing these and returning the results.
|
||||
@ -5618,12 +5711,12 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
|
||||
parent.db.GetAllTypeNodeFiltered(['logintoken-' + user._id], domain.id, 'logintoken', null, function (err, docs) {
|
||||
if (err != null) return;
|
||||
var now = Date.now(), removed = 0, okDocs = [];
|
||||
var now = Date.now(), removed = [], okDocs = [];
|
||||
for (var i = 0; i < docs.length; i++) {
|
||||
const doc = docs[i];
|
||||
if (((doc.expire != 0) && (doc.expire < now)) || (doc.tokenUser == null) || ((command.remove != null) && (command.remove.indexOf(doc.tokenUser) >= 0))) {
|
||||
// This share is expired.
|
||||
parent.db.Remove(doc._id, function () { }); removed++;
|
||||
parent.db.Remove(doc._id, function () { }); removed.push(doc.tokenUser);
|
||||
} else {
|
||||
// This share is ok, remove extra data we don't need to send.
|
||||
delete doc._id; delete doc.domain; delete doc.nodeid; delete doc.type; delete doc.userid; delete doc.salt; delete doc.hash;
|
||||
@ -5633,17 +5726,18 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
|
||||
try { ws.send(JSON.stringify({ action: 'loginTokens', loginTokens: okDocs })); } catch (ex) { }
|
||||
|
||||
// If any login tokens where removed, event the change.
|
||||
if (removed > 0) {
|
||||
if (removed.length > 0) {
|
||||
// Dispatch the new event
|
||||
var targets = ['*', 'server-users', user._id];
|
||||
if (user.groups) { for (var i in user.groups) { targets.push('server-users:' + i); } }
|
||||
var event = { etype: 'user', userid: user._id, username: user.name, action: 'loginTokenChanged', domain: domain.id, loginTokens: okDocs, nolog: 1 };
|
||||
var event = { etype: 'user', userid: user._id, username: user.name, action: 'loginTokenChanged', domain: domain.id, loginTokens: okDocs, removed: removed, nolog: 1 };
|
||||
parent.parent.DispatchEvent(targets, obj, event);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 'createLoginToken': { // Create a new login token
|
||||
if (req.session.loginToken != null) break; // Do not allow this command when logged in using a login token
|
||||
if ((typeof domain.passwordrequirements != 'object') && (domain.passwordrequirements.logintokens == false)) break; // Login tokens are not supported on this server
|
||||
if (common.validateString(command.name, 1, 100) == false) break; // Check name
|
||||
if ((typeof command.expire != 'number') || (command.expire < 0)) break; // Check expire
|
||||
|
2
public/scripts/agent-desktop-0.0.2-min.js
vendored
2
public/scripts/agent-desktop-0.0.2-min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
@ -1349,12 +1349,12 @@
|
||||
}
|
||||
|
||||
function updateSelf() {
|
||||
var accountSettingsLocked = false;
|
||||
if (userinfo) { accountSettingsLocked = ((userinfo.siteadmin != 0xFFFFFFFF) && ((userinfo.siteadmin & 1024) != 0)); }
|
||||
var accountSettingsLocked = ((features2 & 0x100) != 0);
|
||||
if (userinfo) { accountSettingsLocked = ((userinfo.siteadmin != 0xFFFFFFFF) && ((userinfo.siteadmin & 1024) != 0)) || ((features2 & 0x100) != 0); } // Not admin and have account features locked, or using a loginToken
|
||||
QV('p3AccountActions', ((features & 4) == 0) && (serverinfo.domainauth == false) && (accountSettingsLocked == false)); // Hide Account Actions if in single user mode or domain authentication
|
||||
QV('logoutMenuOption', ((features & 4) == 0) && (serverinfo.domainauth == false)); // Hide logout if in single user mode or domain authentication
|
||||
QV('p2AccountSecurity', ((features & 4) == 0) && (serverinfo.domainauth == false) && ((features & 4096) != 0) && (accountSettingsLocked == false)); // Hide Account Security if in single user mode or domain authentication, 2 factor auth not supported.
|
||||
|
||||
QV('p2AccountImage', !accountSettingsLocked);
|
||||
QV('verifyEmailId', (userinfo.emailVerified !== true) && (userinfo.email != null) && (serverinfo.emailcheck == true));
|
||||
QV('manageAuthApp', features & 4096);
|
||||
QV('manageOtp', ((features & 4096) != 0) && ((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0)));
|
||||
|
@ -1928,7 +1928,7 @@
|
||||
function updateSiteAdmin() {
|
||||
var serverFeatures = parseInt('{{{serverfeatures}}}');
|
||||
var siteRights = userinfo.siteadmin;
|
||||
var accountSettingsLocked = ((siteRights != 0xFFFFFFFF) && ((siteRights & 1024) != 0));
|
||||
var accountSettingsLocked = ((siteRights != 0xFFFFFFFF) && ((siteRights & 1024) != 0)) || ((features2 & 0x100) != 0); // Not admin and have account features locked, or using a loginToken
|
||||
|
||||
// Update account actions
|
||||
QV('p2AccountSecurity', ((features & 4) == 0) && (serverinfo.domainauth == false) && ((features & 4096) != 0) && (accountSettingsLocked == false)); // Hide Account Security if in single user mode or domain authentication, 2 factor auth not supported.
|
||||
@ -1939,7 +1939,7 @@
|
||||
QV('p2AccountPassActions', ((features & 4) == 0) && (serverinfo.domainauth == false) && (userinfo != null) && (userinfo._id.split('/')[2].startsWith('~') == false)); // Hide Account Actions if in single user mode or domain authentication
|
||||
//QV('p2AccountImage', ((features & 4) == 0) && (serverinfo.domainauth == false)); // If account actions are not visible, also remove the image on that panel
|
||||
QV('accountCreateLoginTokenSpan', features2 & 0x00000080);
|
||||
QV('p2AccountImage', !accountSettingsLocked)
|
||||
QV('p2AccountImageFrame', !accountSettingsLocked)
|
||||
QV('p2ServerActions', (siteRights & 21) && ((serverFeatures & 15) != 0));
|
||||
QV('LeftMenuMyServer', (siteRights & 21) && ((serverFeatures & 64) != 0)); // 16 + 4 + 1
|
||||
QV('MainMenuMyServer', siteRights & 21);
|
||||
@ -10211,6 +10211,7 @@
|
||||
x += addHtmlValue("Expire Time", '<select id=d2tokenExpire style=width:250px>' + y + '</select>');
|
||||
setDialogMode(2, "Create Login Token", 3, account_createLoginTokenEx, x);
|
||||
QE('idx_dlgOkButton', false);
|
||||
Q('d2tokenName').focus();
|
||||
}
|
||||
|
||||
function account_createLoginTokenValidate() {
|
||||
|
27
webserver.js
27
webserver.js
@ -1164,6 +1164,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
delete req.session.messageid;
|
||||
delete req.session.passhint;
|
||||
delete req.session.cuserid;
|
||||
delete req.session.expire;
|
||||
req.session.userid = userid;
|
||||
req.session.domainid = domain.id;
|
||||
req.session.currentNode = '';
|
||||
@ -1205,6 +1206,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (domain == null) { return; }
|
||||
if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleCreateAccountRequest: failed checks.'); res.sendStatus(404); return; }
|
||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||
if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
|
||||
|
||||
// Check if we are in maintenance mode
|
||||
if (parent.config.settings.maintenancemode != null) {
|
||||
@ -1359,6 +1361,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
const domain = checkUserIpAddress(req, res);
|
||||
if (domain == null) { return; }
|
||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||
if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
|
||||
|
||||
// Check everything is ok
|
||||
if ((domain == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap') || (typeof req.body.rpassword1 != 'string') || (typeof req.body.rpassword2 != 'string') || (req.body.rpassword1 != req.body.rpassword2) || (typeof req.body.rpasswordhint != 'string') || (req.session == null) || (typeof req.session.resettokenusername != 'string') || (typeof req.session.resettokenpassword != 'string')) {
|
||||
@ -1472,6 +1475,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (domain == null) { return; }
|
||||
if ((domain.auth == 'sspi') || (domain.auth == 'ldap') || (obj.args.lanonly == true) || (obj.parent.certificates.CommonName == null) || (obj.parent.certificates.CommonName.indexOf('.') == -1)) { parent.debug('web', 'handleResetAccountRequest: check failed'); res.sendStatus(404); return; }
|
||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||
if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
|
||||
|
||||
// Always lowercase the email address
|
||||
if (req.body.email) { req.body.email = req.body.email.toLowerCase(); }
|
||||
@ -1591,6 +1595,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (domain == null) { return; }
|
||||
if ((domain.mailserver == null) || (domain.auth == 'sspi') || (domain.auth == 'ldap') || (typeof req.session.cuserid != 'string') || (obj.users[req.session.cuserid] == null) || (!obj.common.validateEmail(req.body.email, 1, 256))) { parent.debug('web', 'handleCheckAccountEmailRequest: failed checks.'); res.sendStatus(404); return; }
|
||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||
if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
|
||||
|
||||
// Always lowercase the email address
|
||||
if (req.body.email) { req.body.email = req.body.email.toLowerCase(); }
|
||||
@ -1980,6 +1985,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (domain == null) { return; }
|
||||
if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handleDeleteAccountRequest: failed checks.'); res.sendStatus(404); return; }
|
||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||
if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
|
||||
|
||||
var user = null;
|
||||
if (req.body.authcookie) {
|
||||
@ -2056,6 +2062,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
obj.db.Remove('ntp' + deluser._id); // Remove personal notes for this user
|
||||
obj.db.Remove('im' + deluser._id); // Remove image for this user
|
||||
|
||||
// Delete any login tokens
|
||||
parent.db.GetAllTypeNodeFiltered(['logintoken-' + deluser._id], domain.id, 'logintoken', null, function (err, docs) {
|
||||
if ((err == null) && (docs != null)) { for (var i = 0; i < docs.length; i++) { parent.db.Remove(docs[i]._id, function () { }); } }
|
||||
});
|
||||
|
||||
// Delete all files on the server for this account
|
||||
try {
|
||||
var deluserpath = obj.getServerRootFilePath(deluser);
|
||||
if (deluserpath != null) { obj.deleteFolderRec(deluserpath); }
|
||||
} catch (e) { }
|
||||
|
||||
// Remove the user
|
||||
obj.db.Remove(deluser._id);
|
||||
delete obj.users[deluser._id];
|
||||
@ -2151,6 +2168,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (domain == null) { return; }
|
||||
if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) { parent.debug('web', 'handlePasswordChangeRequest: failed checks (1).'); res.sendStatus(404); return; }
|
||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||
if (req.session.loginToken != null) { res.sendStatus(404); return; } // Do not allow this command when logged in using a login token
|
||||
|
||||
// Check if the user is logged and we have all required parameters
|
||||
if (!req.session || !req.session.userid || !req.body.apassword0 || !req.body.apassword1 || (req.body.apassword1 != req.body.apassword2) || (req.session.domainid != domain.id)) {
|
||||
@ -2325,6 +2343,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if ((domain.loginkey != null) && (domain.loginkey.indexOf(req.query.key) == -1)) { res.sendStatus(404); return; } // Check 3FA URL key
|
||||
if (!obj.args) { parent.debug('web', 'handleRootRequest: no obj.args.'); res.sendStatus(500); return; }
|
||||
|
||||
// If the session is expired, clear it.
|
||||
if ((req.session != null) && (typeof req.session.expire == 'number') && ((req.session.expire - Date.now()) <= 0)) { for (var i in req.session) { delete req.session[i]; } }
|
||||
|
||||
// Check if we are in maintenance mode
|
||||
if ((parent.config.settings.maintenancemode != null) && (req.query.admin !== '1')) {
|
||||
parent.debug('web', 'handleLoginRequest: Server under maintenance.');
|
||||
@ -2584,6 +2605,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
if (parent.amtProvisioningServer != null) { features2 += 0x00000020; } // Intel AMT LAN provisioning server
|
||||
if (((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.push2factor != false)) && (obj.parent.firebase != null)) { features2 += 0x00000040; } // Indicates device push notification 2FA is enabled
|
||||
if ((typeof domain.passwordrequirements != 'object') || (domain.passwordrequirements.logintokens != false)) { features2 += 0x00000080; } // Indicates login tokens are allowed
|
||||
if (req.session.loginToken != null) { features2 += 0x00000100; } // LoginToken mode, no account changes.
|
||||
|
||||
// Create a authentication cookie
|
||||
const authCookie = obj.parent.encodeCookie({ userid: dbGetFunc.user._id, domainid: domain.id, ip: req.clientIp }, obj.parent.loginCookieEncryptionKey);
|
||||
@ -6095,6 +6117,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
|
||||
|
||||
// Authenticates a session and forwards
|
||||
function PerformWSSessionAuth(ws, req, noAuthOk, func) {
|
||||
// Check if the session expired
|
||||
if ((req.session != null) && (typeof req.session.expire == 'number') && (req.session.expire <= Date.now())) {
|
||||
parent.debug('web', 'WSERROR: Session expired.'); try { ws.send(JSON.stringify({ action: 'close', cause: 'expired', msg: 'expired-1' })); ws.close(); } catch (e) { } return;
|
||||
}
|
||||
|
||||
// Check if this is a banned ip address
|
||||
if (obj.checkAllowLogin(req) == false) { parent.debug('web', 'WSERROR: Banned connection.'); try { ws.send(JSON.stringify({ action: 'close', cause: 'banned', msg: 'banned-1' })); ws.close(); } catch (e) { } return; }
|
||||
try {
|
||||
|
Loading…
Reference in New Issue
Block a user