Merge branch 'Ylianst:master' into dockerrewrite

This commit is contained in:
DaanSelen 2025-05-23 10:32:17 +02:00 committed by GitHub
commit 620df54036
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 5333 additions and 5145 deletions

View File

@ -2314,11 +2314,11 @@ function terminal_end()
function terminal_consent_ask(ws) { function terminal_consent_ask(ws) {
ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 })); ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
var consentMessage = currentTranslation['terminalConsent'].replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); var consentMessage = currentTranslation['terminalConsent'].replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username);
var consentTitle = 'MeshCentral'; var consentTitle = 'MeshCentral';
if (ws.httprequest.soptions != null) { if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; } if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; }
if (ws.httprequest.soptions.consentMsgTerminal != null) { consentMessage = ws.httprequest.soptions.consentMsgTerminal.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); } if (ws.httprequest.soptions.consentMsgTerminal != null) { consentMessage = ws.httprequest.soptions.consentMsgTerminal.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
} }
if (process.platform == 'win32') { if (process.platform == 'win32') {
var enhanced = false; var enhanced = false;
@ -2417,12 +2417,12 @@ function terminal_promise_connection_resolved(term)
if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 2)) if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 2))
{ {
// User Notifications is required // User Notifications is required
var notifyMessage = currentTranslation['terminalNotify'].replaceAll('{0}', this.ws.httprequest.realname ? this.ws.httprequest.realname : this.ws.httprequest.username); var notifyMessage = currentTranslation['terminalNotify'].replace(/\{0\}/g, this.ws.httprequest.realname ? this.ws.httprequest.realname : this.ws.httprequest.username);
var notifyTitle = "MeshCentral"; var notifyTitle = "MeshCentral";
if (this.ws.httprequest.soptions != null) if (this.ws.httprequest.soptions != null)
{ {
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; } if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
if (this.ws.httprequest.soptions.notifyMsgTerminal != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgTerminal.replaceAll('{0}', this.ws.httprequest.realname).replaceAll('{1}', this.ws.httprequest.username); } if (this.ws.httprequest.soptions.notifyMsgTerminal != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgTerminal.replace(/\{0\}/g, this.ws.httprequest.realname).replace(/\{1\}/g, this.ws.httprequest.username); }
} }
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { } try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
} }
@ -2431,11 +2431,19 @@ function terminal_promise_connection_resolved(term)
function terminal_promise_consent_rejected(e) function terminal_promise_consent_rejected(e)
{ {
// DO NOT start terminal // DO NOT start terminal
this.that.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 })); if (this.that) {
this.that.end(); if(this.that.httprequest){ // User Consent Denied
if ((this.that.httprequest.oldStyle === true) && (this.that.httprequest.consentAutoAccept === true) && (e.toString() != "7")) {
this.that = null; terminal_promise_consent_resolved.call(this); // oldStyle prompt timed out and User Consent is not required so connect anyway
this.httprequest = null; return;
}
} else { } // Connection was closed server side, maybe log some messages somewhere?
this.that.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: e.toString(), msgid: 2 }));
this.that.end();
this.that = null;
this.httprequest = null;
} else { } // no websocket, maybe log some messages somewhere?
} }
function promise_init(res, rej) { this._res = res; this._rej = rej; } function promise_init(res, rej) { this._res = res; this._rej = rej; }
function terminal_userpromise_resolved(u) function terminal_userpromise_resolved(u)
@ -2646,7 +2654,7 @@ function tunnel_kvm_end()
this.httprequest.desktop.kvm.users.splice(i, 1); this.httprequest.desktop.kvm.users.splice(i, 1);
this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close'); this.httprequest.desktop.kvm.connectionBar.removeAllListeners('close');
this.httprequest.desktop.kvm.connectionBar.close(); this.httprequest.desktop.kvm.connectionBar.close();
this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replaceAll('{0}', this.httprequest.desktop.kvm.rusers.join(', ')).replaceAll('{1}', this.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options); this.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.httprequest.privacybartext.replace(/\{0\}/g, this.httprequest.desktop.kvm.rusers.join(', ')).replace(/\{1\}/g, this.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest; this.httprequest.desktop.kvm.connectionBar.httprequest = this.httprequest;
this.httprequest.desktop.kvm.connectionBar.on('close', function () this.httprequest.desktop.kvm.connectionBar.on('close', function ()
{ {
@ -2682,11 +2690,11 @@ function kvm_consent_ok(ws) {
if (ws.httprequest.consent && (ws.httprequest.consent & 1)){ if (ws.httprequest.consent && (ws.httprequest.consent & 1)){
// User Notifications is required // User Notifications is required
MeshServerLogEx(35, null, "Started remote desktop with toast notification (" + ws.httprequest.remoteaddr + ")", ws.httprequest); MeshServerLogEx(35, null, "Started remote desktop with toast notification (" + ws.httprequest.remoteaddr + ")", ws.httprequest);
var notifyMessage = currentTranslation['desktopNotify'].replaceAll('{0}', ws.httprequest.realname); var notifyMessage = currentTranslation['desktopNotify'].replace(/\{0\}/g, ws.httprequest.realname);
var notifyTitle = "MeshCentral"; var notifyTitle = "MeshCentral";
if (ws.httprequest.soptions != null) { if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.notifyTitle != null) { notifyTitle = ws.httprequest.soptions.notifyTitle; } if (ws.httprequest.soptions.notifyTitle != null) { notifyTitle = ws.httprequest.soptions.notifyTitle; }
if (ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = ws.httprequest.soptions.notifyMsgDesktop.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); } if (ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = ws.httprequest.soptions.notifyMsgDesktop.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
} }
try { require('toaster').Toast(notifyTitle, notifyMessage, ws.tsid); } catch (ex) { } try { require('toaster').Toast(notifyTitle, notifyMessage, ws.tsid); } catch (ex) { }
} else { } else {
@ -2699,7 +2707,7 @@ function kvm_consent_ok(ws) {
ws.httprequest.desktop.kvm.connectionBar.close(); ws.httprequest.desktop.kvm.connectionBar.close();
} }
try { try {
ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(ws.httprequest.privacybartext.replaceAll('{0}', ws.httprequest.desktop.kvm.rusers.join(', ')).replaceAll('{1}', ws.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options); ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(ws.httprequest.privacybartext.replace(/\{0\}/g, ws.httprequest.desktop.kvm.rusers.join(', ')).replace(/\{1\}/g, ws.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + ws.httprequest.remoteaddr + ")", ws.httprequest); MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + ws.httprequest.remoteaddr + ")", ws.httprequest);
} catch (ex) { } catch (ex) {
MeshServerLogEx(32, null, "Remote Desktop Connection Bar Failed or not Supported (" + ws.httprequest.remoteaddr + ")", ws.httprequest); MeshServerLogEx(32, null, "Remote Desktop Connection Bar Failed or not Supported (" + ws.httprequest.remoteaddr + ")", ws.httprequest);
@ -2733,11 +2741,11 @@ function kvm_consent_ok(ws) {
function kvm_consent_ask(ws){ function kvm_consent_ask(ws){
// Send a console message back using the console channel, "\n" is supported. // Send a console message back using the console channel, "\n" is supported.
ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 })); ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
var consentMessage = currentTranslation['desktopConsent'].replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); var consentMessage = currentTranslation['desktopConsent'].replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username);
var consentTitle = 'MeshCentral'; var consentTitle = 'MeshCentral';
if (ws.httprequest.soptions != null) { if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; } if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; }
if (ws.httprequest.soptions.consentMsgDesktop != null) { consentMessage = ws.httprequest.soptions.consentMsgDesktop.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); } if (ws.httprequest.soptions.consentMsgDesktop != null) { consentMessage = ws.httprequest.soptions.consentMsgDesktop.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
} }
var pr; var pr;
if (process.platform == 'win32') { if (process.platform == 'win32') {
@ -2776,6 +2784,10 @@ function kvm_consentpromise_rejected(e)
{ {
if (this.ws) { if (this.ws) {
if(this.ws.httprequest){ // User Consent Denied if(this.ws.httprequest){ // User Consent Denied
if ((this.ws.httprequest.oldStyle === true) && (this.ws.httprequest.consentAutoAccept === true) && (e.toString() != "7")) {
kvm_consentpromise_resolved.call(this); // oldStyle prompt timed out and User Consent is not required so connect anyway
return;
}
MeshServerLogEx(34, null, "Failed to start remote desktop after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest); MeshServerLogEx(34, null, "Failed to start remote desktop after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
} else { } // Connection was closed server side, maybe log some messages somewhere? } else { } // Connection was closed server side, maybe log some messages somewhere?
this.ws._consentpromise = null; this.ws._consentpromise = null;
@ -2794,12 +2806,12 @@ function kvm_consentpromise_resolved(always)
if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 1)) if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 1))
{ {
// User Notifications is required // User Notifications is required
var notifyMessage = currentTranslation['desktopNotify'].replaceAll('{0}', this.ws.httprequest.realname); var notifyMessage = currentTranslation['desktopNotify'].replace(/\{0\}/g, this.ws.httprequest.realname);
var notifyTitle = "MeshCentral"; var notifyTitle = "MeshCentral";
if (this.ws.httprequest.soptions != null) if (this.ws.httprequest.soptions != null)
{ {
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; } if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
if (this.ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgDesktop.replaceAll('{0}', this.ws.httprequest.realname).replaceAll('{1}', this.ws.httprequest.username); } if (this.ws.httprequest.soptions.notifyMsgDesktop != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgDesktop.replace(/\{0\}/g, this.ws.httprequest.realname).replace(/\{1\}/g, this.ws.httprequest.username); }
} }
try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (ex) { } try { require('toaster').Toast(notifyTitle, notifyMessage, tsid); } catch (ex) { }
} }
@ -2813,7 +2825,7 @@ function kvm_consentpromise_resolved(always)
} }
try try
{ {
this.ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.ws.httprequest.privacybartext.replaceAll('{0}', this.ws.httprequest.desktop.kvm.rusers.join(', ')).replaceAll('{1}', this.ws.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options); this.ws.httprequest.desktop.kvm.connectionBar = require('notifybar-desktop')(this.ws.httprequest.privacybartext.replace(/\{0\}/g, this.ws.httprequest.desktop.kvm.rusers.join(', ')).replace(/\{1\}/g, this.ws.httprequest.desktop.kvm.users.join(', ')).replace(/'/g, "\\'\\"), require('MeshAgent')._tsid, color_options);
MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest); MeshServerLogEx(31, null, "Remote Desktop Connection Bar Activated/Updated (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
} catch (ex) } catch (ex)
{ {
@ -2856,11 +2868,11 @@ function files_consent_ok(ws){
if (ws.httprequest.consent && (ws.httprequest.consent & 4)) { if (ws.httprequest.consent && (ws.httprequest.consent & 4)) {
// User Notifications is required // User Notifications is required
MeshServerLogEx(42, null, "Started remote files with toast notification (" + ws.httprequest.remoteaddr + ")", ws.httprequest); MeshServerLogEx(42, null, "Started remote files with toast notification (" + ws.httprequest.remoteaddr + ")", ws.httprequest);
var notifyMessage = currentTranslation['fileNotify'].replaceAll('{0}', ws.httprequest.realname); var notifyMessage = currentTranslation['fileNotify'].replace(/\{0\}/g, ws.httprequest.realname);
var notifyTitle = "MeshCentral"; var notifyTitle = "MeshCentral";
if (ws.httprequest.soptions != null) { if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.notifyTitle != null) { notifyTitle = ws.httprequest.soptions.notifyTitle; } if (ws.httprequest.soptions.notifyTitle != null) { notifyTitle = ws.httprequest.soptions.notifyTitle; }
if (ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = ws.httprequest.soptions.notifyMsgFiles.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); } if (ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = ws.httprequest.soptions.notifyMsgFiles.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
} }
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { } try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
} else { } else {
@ -2872,12 +2884,12 @@ function files_consent_ok(ws){
function files_consent_ask(ws){ function files_consent_ask(ws){
// Send a console message back using the console channel, "\n" is supported. // Send a console message back using the console channel, "\n" is supported.
ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 })); ws.write(JSON.stringify({ ctrlChannel: '102938', type: 'console', msg: "Waiting for user to grant access...", msgid: 1 }));
var consentMessage = currentTranslation['fileConsent'].replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); var consentMessage = currentTranslation['fileConsent'].replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username);
var consentTitle = 'MeshCentral'; var consentTitle = 'MeshCentral';
if (ws.httprequest.soptions != null) { if (ws.httprequest.soptions != null) {
if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; } if (ws.httprequest.soptions.consentTitle != null) { consentTitle = ws.httprequest.soptions.consentTitle; }
if (ws.httprequest.soptions.consentMsgFiles != null) { consentMessage = ws.httprequest.soptions.consentMsgFiles.replaceAll('{0}', ws.httprequest.realname).replaceAll('{1}', ws.httprequest.username); } if (ws.httprequest.soptions.consentMsgFiles != null) { consentMessage = ws.httprequest.soptions.consentMsgFiles.replace(/\{0\}/g, ws.httprequest.realname).replace(/\{1\}/g, ws.httprequest.username); }
} }
var pr; var pr;
if (process.platform == 'win32') { if (process.platform == 'win32') {
@ -2923,12 +2935,12 @@ function files_consentpromise_resolved(always)
if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 4)) if (this.ws.httprequest.consent && (this.ws.httprequest.consent & 4))
{ {
// User Notifications is required // User Notifications is required
var notifyMessage = currentTranslation['fileNotify'].replaceAll('{0}', this.ws.httprequest.realname); var notifyMessage = currentTranslation['fileNotify'].replace(/\{0\}/g, this.ws.httprequest.realname);
var notifyTitle = "MeshCentral"; var notifyTitle = "MeshCentral";
if (this.ws.httprequest.soptions != null) if (this.ws.httprequest.soptions != null)
{ {
if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; } if (this.ws.httprequest.soptions.notifyTitle != null) { notifyTitle = this.ws.httprequest.soptions.notifyTitle; }
if (this.ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgFiles.replaceAll('{0}', this.ws.httprequest.realname).replaceAll('{1}', this.ws.httprequest.username); } if (this.ws.httprequest.soptions.notifyMsgFiles != null) { notifyMessage = this.ws.httprequest.soptions.notifyMsgFiles.replace(/\{0\}/g, this.ws.httprequest.realname).replace(/\{1\}/g, this.ws.httprequest.username); }
} }
try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { } try { require('toaster').Toast(notifyTitle, notifyMessage); } catch (ex) { }
} }
@ -2939,6 +2951,10 @@ function files_consentpromise_rejected(e)
{ {
if (this.ws) { if (this.ws) {
if(this.ws.httprequest){ // User Consent Denied if(this.ws.httprequest){ // User Consent Denied
if ((this.ws.httprequest.oldStyle === true) && (this.ws.httprequest.consentAutoAccept === true) && (e.toString() != "7")) {
files_consentpromise_resolved.call(this); // oldStyle prompt timed out and User Consent is not required so connect anyway
return;
}
MeshServerLogEx(41, null, "Failed to start remote files after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest); MeshServerLogEx(41, null, "Failed to start remote files after local user rejected (" + this.ws.httprequest.remoteaddr + ")", this.ws.httprequest);
} else { } // Connection was closed server side, maybe log some messages somewhere? } else { } // Connection was closed server side, maybe log some messages somewhere?
this.ws._consentpromise = null; this.ws._consentpromise = null;

View File

@ -2890,7 +2890,7 @@
"items": { "items": {
"type": "integer" "type": "integer"
}, },
"description": "This is an array: 1 = Terminal, 2 = Desktop, 5 = Files, 100 = Intel AMT WSMAN, 101 = Intel AMT Redirection, 200 = Messenger" "description": "This is an array: 1 = Terminal, 2 = Desktop, 5 = Files, 6 = Admin Powershell, 8 = User Shell, 9 = User Powershell, 100 = Intel AMT WSMAN, 101 = Intel AMT Redirection, 200 = Messenger"
} }
}, },
"required": [ "required": [

View File

@ -997,7 +997,7 @@ function CreateMeshCentralServer(config, args) {
if (err != null) { console.log("Database error: " + err); process.exit(); return; } if (err != null) { console.log("Database error: " + err); process.exit(); return; }
if ((docs == null) || (docs.length == 0)) { console.log("Unknown userid, usage: --resetaccount [userid] --domain (domain) --pass [password]."); process.exit(); return; } if ((docs == null) || (docs.length == 0)) { console.log("Unknown userid, usage: --resetaccount [userid] --domain (domain) --pass [password]."); process.exit(); return; }
const user = docs[0]; if ((user.siteadmin) && (user.siteadmin != 0xFFFFFFFF) && (user.siteadmin & 32) != 0) { user.siteadmin -= 32; } // Unlock the account. const user = docs[0]; if ((user.siteadmin) && (user.siteadmin != 0xFFFFFFFF) && (user.siteadmin & 32) != 0) { user.siteadmin -= 32; } // Unlock the account.
delete user.phone; delete user.otpekey; delete user.otpsecret; delete user.otpkeys; delete user.otphkeys; delete user.otpdev; delete user.otpsms; delete user.otpmsg; // Disable 2FA delete user.phone; delete user.otpekey; delete user.otpsecret; delete user.otpkeys; delete user.otphkeys; delete user.otpdev; delete user.otpsms; delete user.otpmsg; user.otpduo; // Disable 2FA
delete user.msghandle; // Disable users 2fa messaging too delete user.msghandle; // Disable users 2fa messaging too
var config = getConfig(false); var config = getConfig(false);
if (config.domains[user.domain].auth || config.domains[user.domain].authstrategies) { if (config.domains[user.domain].auth || config.domains[user.domain].authstrategies) {

View File

@ -42,6 +42,9 @@ const MESHRIGHT_ADMIN = 0xFFFFFFFF;
// 1 = Terminal // 1 = Terminal
// 2 = Desktop // 2 = Desktop
// 5 = Files // 5 = Files
// 6 = Admin PowerShell
// 8 = User Shell
// 9 = User PowerShell
// 10 = Web-RDP // 10 = Web-RDP
// 11 = Web-SSH // 11 = Web-SSH
// 12 = Web-VNC // 12 = Web-VNC
@ -578,7 +581,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
// Log the connection // Log the connection
if (sessionUser != null) { if (sessionUser != null) {
var msg = 'Started relay session', msgid = 13; var msg = 'Started relay session', msgid = 13;
if (obj.req.query.p == 1) { msg = 'Started terminal session'; msgid = 14; } if ([1,6,8,9].indexOf(obj.req.query.p) >= 0) { msg = 'Started terminal session'; msgid = 14; } // admin shell, admin powershell, user shell, user powershell
else if (obj.req.query.p == 2) { msg = 'Started desktop session'; msgid = 15; } else if (obj.req.query.p == 2) { msg = 'Started desktop session'; msgid = 15; }
else if (obj.req.query.p == 5) { msg = 'Started file management session'; msgid = 16; } else if (obj.req.query.p == 5) { msg = 'Started file management session'; msgid = 16; }
else if (obj.req.query.p == 200) { msg = 'Started messenger session'; msgid = 162; } else if (obj.req.query.p == 200) { msg = 'Started messenger session'; msgid = 162; }
@ -777,7 +780,7 @@ function CreateMeshRelayEx(parent, ws, req, domain, user, cookie) {
// Log the disconnection // Log the disconnection
if (ws.time) { if (ws.time) {
var msg = 'Ended relay session', msgid = 9; var msg = 'Ended relay session', msgid = 9;
if (obj.req.query.p == 1) { msg = 'Ended terminal session', msgid = 10; } if ([1,6,8,9].indexOf(obj.req.query.p) >= 0) { msg = 'Ended terminal session', msgid = 10; } // admin shell, admin powershell, user shell, user powershell
else if (obj.req.query.p == 2) { msg = 'Ended desktop session', msgid = 11; } else if (obj.req.query.p == 2) { msg = 'Ended desktop session', msgid = 11; }
else if (obj.req.query.p == 5) { msg = 'Ended file management session', msgid = 12; } else if (obj.req.query.p == 5) { msg = 'Ended file management session', msgid = 12; }
else if (obj.req.query.p == 200) { msg = 'Ended messenger session', msgid = 112; } else if (obj.req.query.p == 200) { msg = 'Ended messenger session', msgid = 112; }

View File

@ -1973,6 +1973,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
delete chguser.otpekey; // Email 2FA delete chguser.otpekey; // Email 2FA
delete chguser.phone; // SMS 2FA delete chguser.phone; // SMS 2FA
delete chguser.otpdev; // Push notification 2FA delete chguser.otpdev; // Push notification 2FA
delete chguser.otpduo; // Duo 2FA
} }
db.SetUser(chguser); db.SetUser(chguser);

View File

@ -1,6 +1,6 @@
{ {
"name": "meshcentral", "name": "meshcentral",
"version": "1.1.44", "version": "1.1.45",
"keywords": [ "keywords": [
"Remote Device Management", "Remote Device Management",
"Remote Device Monitoring", "Remote Device Monitoring",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -2300,7 +2300,7 @@
if (idtype == 'devices') { go(2); } if (idtype == 'devices') { go(2); }
if (idtype == 'files') { if (idtype == 'files') {
// Remind the user to add two factor authentication // Remind the user to add two factor authentication
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; } if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || (userinfo.otpduo > 0) || (userinfo.otpdev > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
go(5); go(5);
} }
} }
@ -2583,7 +2583,7 @@
if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" to change and verify an email address."); return; } if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" to change and verify an email address."); return; }
// Remind the user to add two factor authentication // Remind the user to add two factor authentication
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; } if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || (userinfo.otpduo > 0) || (userinfo.otpdev > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
// We are allowed, let's prompt to information // We are allowed, let's prompt to information
var x = addHtmlValue("Name", '<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />'); var x = addHtmlValue("Name", '<input id=dp3meshname style=width:170px maxlength=64 onchange=account_validateMeshCreate() onkeyup=account_validateMeshCreate() />');
@ -2677,7 +2677,7 @@
function gotoMesh(meshid) { function gotoMesh(meshid) {
// Remind the user to add two factor authentication // Remind the user to add two factor authentication
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; } if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || (userinfo.otpduo > 0) || (userinfo.otpdev > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access this feature until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
currentMesh = meshes[meshid]; currentMesh = meshes[meshid];
if (currentMesh == null) { goBack(); } if (currentMesh == null) { goBack(); }
p20updateMesh(); p20updateMesh();
@ -3681,7 +3681,7 @@
if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" to change and verify an email address."); return; } if ((userinfo.emailVerified !== true) && (serverinfo.emailcheck == true) && (userinfo.siteadmin != 0xFFFFFFFF)) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until a email address is verified. This is required for password recovery. Go to the \"My Account\" to change and verify an email address."); return; }
// Remind the user to add two factor authentication // Remind the user to add two factor authentication
if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; } if ((features & 0x00040000) && !((userinfo.otpsecret == 1) || (userinfo.otphkeys > 0) || (userinfo.otpkeys > 0) || (userinfo.otpduo > 0) || (userinfo.otpdev > 0) || ((features & 0x00800000) && (userinfo.otpekey == 1)))) { setDialogMode(2, "Account Security", 1, null, "Unable to access a device until two-factor authentication is enabled. This is required for extra security. Go to the \"My Account\" and look at the \"Account Security\" section."); return; }
var node = getNodeFromId(nodeid); var node = getNodeFromId(nodeid);
if (node == null) { goBack(); return; } if (node == null) { goBack(); return; }
@ -7631,7 +7631,16 @@
function printDateTime(d) { return d.toLocaleString(args.locale); } function printDateTime(d) { return d.toLocaleString(args.locale); }
function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); }; function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
function nobreak(x) { return x.split(' ').join('&nbsp;'); } function nobreak(x) { return x.split(' ').join('&nbsp;'); }
function getUserName(userid) { if (users && users[userid] != null) return users[userid].name; return userid.split('/')[2]; } function getUserName(userid) {
var useridsplit = userid.split('/'), userid2 = useridsplit[0] + '/' + useridsplit[1] + '/' + useridsplit[2], guestname = '';
if ((useridsplit.length == 4) && (useridsplit[3].startsWith('guest:'))) { guestname = ' - ' + decode_utf8(atob(useridsplit[3].substring(6))); }
if (users && users[userid2] != null) { if (users[userid2].realname != null) return (users[userid2].realname + guestname); else return (users[userid2].name + guestname); }
if (currentNode && currentNode.links && currentNode.links[userid] && currentNode.links[userid].name != null) { return (currentNode.links[userid].name + guestname); }
if (userid == userinfo._id) { return (userinfo.name + guestname); }
if (nodes) { for (var a in nodes) { if (nodes[a].links) { for (var b in nodes[a].links) { if (nodes[a].links[b].name && b == userid) return (nodes[a].links[b].name + guestname); } } } }
if (meshes) { for (var a in meshes) { if (meshes[a].links) { for (var b in meshes[a].links) { if (meshes[a].links[b].name && b == userid) return (meshes[a].links[b].name + guestname); } } } }
return (useridsplit[2] + guestname);
}
function addDetailItem(title, value, state) { return '<table style=width:100%><td>' + nobreak(title) + '<td style=text-align:right>' + value + '</table>'; } function addDetailItem(title, value, state) { return '<table style=width:100%><td>' + nobreak(title) + '<td style=text-align:right>' + value + '</table>'; }
function isPrivateIP(a) { return (a.startsWith('10.') || a.startsWith('172.16.') || a.startsWith('192.168.')); } function isPrivateIP(a) { return (a.startsWith('10.') || a.startsWith('172.16.') || a.startsWith('192.168.')); }
function encodeURIComponentEx(txt) { return encodeURIComponent(txt).replace(/'/g, '%27'); }; function encodeURIComponentEx(txt) { return encodeURIComponent(txt).replace(/'/g, '%27'); };

View File

@ -326,7 +326,7 @@
<input type=button id=SelectAllButton onclick="selectallButtonFunction();" value="Select All" />&nbsp; <input type=button id=SelectAllButton onclick="selectallButtonFunction();" value="Select All" />&nbsp;
<input type=button id=GroupActionButton disabled="disabled" value="Group Action" onclick=groupActionFunction() />&nbsp; <input type=button id=GroupActionButton disabled="disabled" value="Group Action" onclick=groupActionFunction() />&nbsp;
<input type=button id=ScrollToTopButton onclick="onDevicesScroll(true);" style="display:none;margin-right:4px" value="Scroll To Top" /> <input type=button id=ScrollToTopButton onclick="onDevicesScroll(true);" style="display:none;margin-right:4px" value="Scroll To Top" />
<input id=SearchInput type=input autocomplete=off placeholder=Filter onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any"/>&nbsp; <input id=SearchInput type=input autocomplete=off placeholder=Filter onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any connectivity:xxx c:xxx"/>&nbsp;
<span id=SearchInputClearButton style="display:none;position:relative"><img src="images/x16.png" type="button" onclick="clearDeviceSearch()" style="position:absolute;cursor:pointer;left:-18px;top:-8px" srcset="images/x32.png 2x"/></span> <span id=SearchInputClearButton style="display:none;position:relative"><img src="images/x16.png" type="button" onclick="clearDeviceSearch()" style="position:absolute;cursor:pointer;left:-18px;top:-8px" srcset="images/x32.png 2x"/></span>
<select id=DevFilterSelect onchange=onOnlineCheckBox(event) title="Device Filter"> <select id=DevFilterSelect onchange=onOnlineCheckBox(event) title="Device Filter">
<option value=0>All</option> <option value=0>All</option>
@ -2368,6 +2368,8 @@
if (userinfo == null) return -1; if (userinfo == null) return -1;
var authFactorCount = 0; var authFactorCount = 0;
if (userinfo.otpsecret == 1) { authFactorCount++; } // Authenticator time factor if (userinfo.otpsecret == 1) { authFactorCount++; } // Authenticator time factor
if (userinfo.otpduo == 1) { authFactorCount++; } // Duo factor
if (userinfo.otpdev == 1) { authFactorCount++; } // Push authentication factor
if (userinfo.otphkeys > 0) { authFactorCount += userinfo.otphkeys; } // FIDO hardware factor if (userinfo.otphkeys > 0) { authFactorCount += userinfo.otphkeys; } // FIDO hardware factor
if ((features & 0x00800000) && (userinfo.otpekey == 1)) { authFactorCount++; } // EMail factor if ((features & 0x00800000) && (userinfo.otpekey == 1)) { authFactorCount++; } // EMail factor
if ((features & 0x02000000) && (features & 0x04000000) && (userinfo.phone != null)) { authFactorCount++; } // SMS factor if ((features & 0x02000000) && (features & 0x04000000) && (userinfo.phone != null)) { authFactorCount++; } // SMS factor
@ -6324,7 +6326,7 @@
function getDevicesThatMatchFilter(x) { function getDevicesThatMatchFilter(x) {
var r = []; var r = [];
var userSearch = null, ipSearch = null, groupSearch = null, tagSearch = null, agentTagSearch = null, wscSearch = null, osSearch = null, amtSearch = null, descSearch = null; var userSearch = null, ipSearch = null, groupSearch = null, tagSearch = null, agentTagSearch = null, wscSearch = null, osSearch = null, amtSearch = null, descSearch = null, connectivitySearch = null;
if (x.startsWith("user:".toLowerCase())) { userSearch = x.substring("user:".length); } if (x.startsWith("user:".toLowerCase())) { userSearch = x.substring("user:".length); }
else if (x.startsWith("u:".toLowerCase())) { userSearch = x.substring("u:".length); } else if (x.startsWith("u:".toLowerCase())) { userSearch = x.substring("u:".length); }
else if (x.startsWith("ip:".toLowerCase())) { ipSearch = x.substring("ip:".length); } else if (x.startsWith("ip:".toLowerCase())) { ipSearch = x.substring("ip:".length); }
@ -6337,6 +6339,8 @@
else if (x.startsWith("os:".toLowerCase())) { osSearch = x.substring("os:".length); } else if (x.startsWith("os:".toLowerCase())) { osSearch = x.substring("os:".length); }
else if (x.startsWith("amt:".toLowerCase())) { amtSearch = x.substring("amt:".length); } else if (x.startsWith("amt:".toLowerCase())) { amtSearch = x.substring("amt:".length); }
else if (x.startsWith("desc:".toLowerCase())) { descSearch = x.substring("desc:".length); } else if (x.startsWith("desc:".toLowerCase())) { descSearch = x.substring("desc:".length); }
else if (x.startsWith("connectivity:".toLowerCase())) { connectivitySearch = x.substring("connectivity:".length); }
else if (x.startsWith("c:".toLowerCase())) { connectivitySearch = x.substring("c:".length); }
else if (x == 'wsc:ok') { wscSearch = 1; } else if (x == 'wsc:ok') { wscSearch = 1; }
else if (x == 'wsc:noav') { wscSearch = 2; } else if (x == 'wsc:noav') { wscSearch = 2; }
else if (x == 'wsc:noupdate') { wscSearch = 3; } else if (x == 'wsc:noupdate') { wscSearch = 3; }
@ -6387,6 +6391,35 @@
else if (((wscSearch == 4) || (wscSearch == 5)) && (nodes[d].wsc.firewall != 'OK')) { r.push(d); } else if (((wscSearch == 4) || (wscSearch == 5)) && (nodes[d].wsc.firewall != 'OK')) { r.push(d); }
} }
} }
} else if (connectivitySearch != null) {
// Connectivity search
for (var d in nodes) {
if (nodes[d].conn) {
if ((nodes[d].conn & 1) != 0) {
if (nodes[d].mtype == 4) {
if ((nodes[d].porttype == 'PDU') && (connectivitySearch.toLowerCase() == 'switch')) {
r.push(d);
} else if (connectivitySearch.toLowerCase() == 'ipkvm') {
r.push(d);
}
} else if (connectivitySearch.toLowerCase() == 'agent') {
r.push(d);
}
}
if (((nodes[d].conn & 2) != 0) && (connectivitySearch.toLowerCase() == 'cira')) { r.push(d); }
else if (((nodes[d].conn & 4) != 0) && (connectivitySearch.toLowerCase() == 'amt')) { r.push(d); }
if (((nodes[d].conn & 8) != 0) && (connectivitySearch.toLowerCase() == 'relay')) { r.push(d); }
if (((nodes[d].conn & 16) != 0) && (connectivitySearch.toLowerCase() == 'mqtt')) { r.push(d); }
}
if (nodes[d].mtype == 3) {
var mesh = meshes[nodes[d].meshid];
if (mesh && mesh.relayid && (connectivitySearch.toLowerCase() == 'relay')) {
r.push(d);
} else if (mesh && (typeof mesh.relayid == 'undefined') && connectivitySearch.toLowerCase() == 'local') {
r.push(d);
}
}
}
} else if (x == '*') { } else if (x == '*') {
// Star filter // Star filter
for (var d in nodes) { if (stars[nodes[d]._id] == 1) { r.push(d); } } for (var d in nodes) { if (stars[nodes[d]._id] == 1) { r.push(d); } }
@ -9852,7 +9885,7 @@
// If shift is pressed, enter browser full screen. // If shift is pressed, enter browser full screen.
if (e.shiftKey == true) { if (e.shiftKey == true) {
enterBrowserFullscreen(Q('container')); enterBrowserFullscreen(Q('body'));
browserfullscreen = true; browserfullscreen = true;
} }
} else { } else {
@ -17467,6 +17500,9 @@
if (rec.protocol == 1) { sessionName += ' - ' + "Terminal Session"; } if (rec.protocol == 1) { sessionName += ' - ' + "Terminal Session"; }
if (rec.protocol == 2) { sessionName += ' - ' + "Desktop Session"; } if (rec.protocol == 2) { sessionName += ' - ' + "Desktop Session"; }
if (rec.protocol == 5) { sessionName += ' - ' + "File Transfer"; } if (rec.protocol == 5) { sessionName += ' - ' + "File Transfer"; }
if (rec.protocol == 6) { sessionName += ' - ' + "Admin PowerShell"; }
if (rec.protocol == 8) { sessionName += ' - ' + "User Shell"; }
if (rec.protocol == 9) { sessionName += ' - ' + "User PowerShell"; }
if (rec.protocol == 100) { sessionName += ' - ' + "Intel&reg; AMT WSMAN"; } if (rec.protocol == 100) { sessionName += ' - ' + "Intel&reg; AMT WSMAN"; }
if (rec.protocol == 101) { sessionName += ' - ' + "Intel&reg; AMT Redirection"; } if (rec.protocol == 101) { sessionName += ' - ' + "Intel&reg; AMT Redirection"; }
if (rec.protocol == 200) { sessionName += ' - ' + "Messenger"; } if (rec.protocol == 200) { sessionName += ' - ' + "Messenger"; }
@ -17497,6 +17533,9 @@
if (rec.protocol == 1) { protocolStr = "Terminal"; } if (rec.protocol == 1) { protocolStr = "Terminal"; }
if (rec.protocol == 2) { protocolStr = "Desktop"; } if (rec.protocol == 2) { protocolStr = "Desktop"; }
if (rec.protocol == 5) { protocolStr = "Files"; } if (rec.protocol == 5) { protocolStr = "Files"; }
if (rec.protocol == 6) { protocolStr = "Admin PowerShell"; }
if (rec.protocol == 8) { protocolStr = "User Shell"; }
if (rec.protocol == 9) { protocolStr = "User PowerShell"; }
if (rec.protocol == 100) { protocolStr = "Intel&reg; AMT WSMAN"; } if (rec.protocol == 100) { protocolStr = "Intel&reg; AMT WSMAN"; }
if (rec.protocol == 101) { protocolStr = "Intel&reg; AMT Redirection"; } if (rec.protocol == 101) { protocolStr = "Intel&reg; AMT Redirection"; }
if (rec.protocol == 200) { protocolStr = "Messenger"; } if (rec.protocol == 200) { protocolStr = "Messenger"; }
@ -17839,6 +17878,9 @@
if (v == 1) return "Terminal"; if (v == 1) return "Terminal";
if (v == 2) return "Desktop"; if (v == 2) return "Desktop";
if (v == 5) return "Files"; if (v == 5) return "Files";
if (v == 6) return "Admin PowerShell";
if (v == 8) return "User Shell";
if (v == 9) return "User PowerShell";
if (v == 100) return "AMT-WSMAN"; if (v == 100) return "AMT-WSMAN";
if (v == 101) return "AMT-Redir"; if (v == 101) return "AMT-Redir";
if (v == 200) return "Messenger"; if (v == 200) return "Messenger";
@ -17940,7 +17982,17 @@
if (v == 1) return "Terminal"; if (v == 1) return "Terminal";
if (v == 2) return "Desktop"; if (v == 2) return "Desktop";
if (v == 5) return "Files"; if (v == 5) return "Files";
return "Unknown"; if (v == 6) return "Admin PowerShell";
if (v == 8) return "User Shell";
if (v == 9) return "User PowerShell";
if (v == 100) return "AMT-WSMAN";
if (v == 101) return "AMT-Redir";
if (v == 200) return "Messenger";
if (v == 201) return "Web-RDP";
if (v == 202) return "Web-SSH";
if (v == 203) return "Web-SFTP";
if (v == 204) return "Web-VNC";
return "Unknown" + ' (' + v + ')';
} }
if (f == 'node') { if (f == 'node') {
var node = getNodeFromId(v); var node = getNodeFromId(v);
@ -19330,6 +19382,7 @@
if (currentNode && currentNode.links && currentNode.links[userid] && currentNode.links[userid].name != null) { return (currentNode.links[userid].name + guestname); } if (currentNode && currentNode.links && currentNode.links[userid] && currentNode.links[userid].name != null) { return (currentNode.links[userid].name + guestname); }
if (userid == userinfo._id) { return (userinfo.name + guestname); } if (userid == userinfo._id) { return (userinfo.name + guestname); }
if (nodes) { for (var a in nodes) { if (nodes[a].links) { for (var b in nodes[a].links) { if (nodes[a].links[b].name && b == userid) return (nodes[a].links[b].name + guestname); } } } } if (nodes) { for (var a in nodes) { if (nodes[a].links) { for (var b in nodes[a].links) { if (nodes[a].links[b].name && b == userid) return (nodes[a].links[b].name + guestname); } } } }
if (meshes) { for (var a in meshes) { if (meshes[a].links) { for (var b in meshes[a].links) { if (meshes[a].links[b].name && b == userid) return (meshes[a].links[b].name + guestname); } } } }
return (useridsplit[2] + guestname); return (useridsplit[2] + guestname);
} }
function round(value, precision) { var multiplier = Math.pow(10, precision || 0); return Math.round(value * multiplier) / multiplier; } function round(value, precision) { var multiplier = Math.pow(10, precision || 0); return Math.round(value * multiplier) / multiplier; }

View File

@ -16,7 +16,6 @@
<link type="text/css" href="styles/xterm.css" media="screen" rel="stylesheet" title="CSS" /> <link type="text/css" href="styles/xterm.css" media="screen" rel="stylesheet" title="CSS" />
<link type="text/css" href="styles/flatpickr.min.css" media="screen" rel="stylesheet" title="CSS"> <link type="text/css" href="styles/flatpickr.min.css" media="screen" rel="stylesheet" title="CSS">
<link id="theme-stylesheet" href="styles/bootstrap{{{min}}}.css" rel="stylesheet" title="CSS"> <link id="theme-stylesheet" href="styles/bootstrap{{{min}}}.css" rel="stylesheet" title="CSS">
<link href="styles/sweetalert2.min.css" rel="stylesheet" title="CSS">
<link href="styles/select2.min.css" rel="stylesheet" title="CSS"> <link href="styles/select2.min.css" rel="stylesheet" title="CSS">
<link href="styles/select2-bootstrap-5-theme.min.css" rel="stylesheet" title="CSS"> <link href="styles/select2-bootstrap-5-theme.min.css" rel="stylesheet" title="CSS">
<link rel="apple-touch-icon" href="/favicon-303x303.png" /> <link rel="apple-touch-icon" href="/favicon-303x303.png" />
@ -48,7 +47,6 @@
<script type="text/javascript" src="scripts/jquery{{{min}}}.js"></script> <script type="text/javascript" src="scripts/jquery{{{min}}}.js"></script>
<script type="text/javascript" src="scripts/bootstrap{{{min}}}.js"></script> <script type="text/javascript" src="scripts/bootstrap{{{min}}}.js"></script>
<script type="text/javascript" src="scripts/fontawesome/all.min.js"></script> <script type="text/javascript" src="scripts/fontawesome/all.min.js"></script>
<script type="text/javascript" src="scripts/sweetalert2.all.min.js"></script>
<script type="text/javascript" src="scripts/select2.full.min.js"></script> <script type="text/javascript" src="scripts/select2.full.min.js"></script>
<script type="text/javascript" src="scripts/themes/theme-switcher.js"></script> <script type="text/javascript" src="scripts/themes/theme-switcher.js"></script>
<script keeplink=1 type="text/javascript" src="scripts/u2f-api{{{min}}}.js"></script> <script keeplink=1 type="text/javascript" src="scripts/u2f-api{{{min}}}.js"></script>
@ -415,7 +413,7 @@
<input type=button class="btn btn-primary me-1 btn-sm" id=SelectAllButton onclick="selectallButtonFunction();" value="Select All" /> <input type=button class="btn btn-primary me-1 btn-sm" id=SelectAllButton onclick="selectallButtonFunction();" value="Select All" />
<input type=button class="btn btn-primary me-1 btn-sm" id=GroupActionButton disabled="disabled" value="Group Action" onclick=groupActionFunction() /> <input type=button class="btn btn-primary me-1 btn-sm" id=GroupActionButton disabled="disabled" value="Group Action" onclick=groupActionFunction() />
<input type=button class="btn btn-primary me-1 btn-sm" id=ScrollToTopButton onclick="onDevicesScroll(true);" value="Scroll To Top" /> <input type=button class="btn btn-primary me-1 btn-sm" id=ScrollToTopButton onclick="onDevicesScroll(true);" value="Scroll To Top" />
<input type="text" id=SearchInput class="form-control-sm me-1 btn-sm" placeholder="Filter" onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any"> <input type="text" id=SearchInput class="form-control-sm me-1 btn-sm" placeholder="Filter" onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any connectivity:xxx c:xxx">
<span id=SearchInputClearButton style="display:none;position:relative"> <span id=SearchInputClearButton style="display:none;position:relative">
<span class="fa-layers fa-fw" role="button" onclick="clearDeviceSearch()" style="position:absolute;left:-25px;top:-15px"> <span class="fa-layers fa-fw" role="button" onclick="clearDeviceSearch()" style="position:absolute;left:-25px;top:-15px">
<i class="fa-solid fa-circle" style="color:var(--bs-secondary-bg)"></i> <i class="fa-solid fa-circle" style="color:var(--bs-secondary-bg)"></i>
@ -451,7 +449,7 @@
<input type="button" class="btn btn-primary me-1 btn-sm" onclick="onDevicesScroll(true);" value="Scroll To Top" /> <input type="button" class="btn btn-primary me-1 btn-sm" onclick="onDevicesScroll(true);" value="Scroll To Top" />
<div class="form-check me-1" title="Automatic connect"><input class="form-check-input me-1" type=checkbox id="autoConnectDesktopCheckbox" onclick="autoConnectDesktops(event)" /><label class="form-check-label" for="autoConnectDesktopCheckbox">Auto</label></div> <div class="form-check me-1" title="Automatic connect"><input class="form-check-input me-1" type=checkbox id="autoConnectDesktopCheckbox" onclick="autoConnectDesktops(event)" /><label class="form-check-label" for="autoConnectDesktopCheckbox">Auto</label></div>
<input type="button" class="btn btn-primary me-1 btn-sm" onclick="showMultiDesktopSettings()" value="Settings" /> <input type="button" class="btn btn-primary me-1 btn-sm" onclick="showMultiDesktopSettings()" value="Settings" />
<input type="text" id=KvmSearchInput class="form-control-sm me-1" placeholder="Filter" onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any"> <input type="text" id=KvmSearchInput class="form-control-sm me-1" placeholder="Filter" onchange=onDeviceSearchChanged(event) onclick=onDeviceSearchChanged(event) onkeyup=onDeviceSearchChanged(event) onfocus=onSearchFocus(1) onblur=onSearchFocus(0) title="Filter: user:xxx or u:xxx ip:xxx group:xxx or g:xxx tag:xxx or t: xxx atag:xxx or a:xxx os:xxx amt:xxx desc:xxx wsc:ok wsc:noav wsc:noupdate wsc:nofirewall wsc:any connectivity:xxx c:xxx">
<span id=KvmSearchInputClearButton style="display:none;position:relative"> <span id=KvmSearchInputClearButton style="display:none;position:relative">
<span class="fa-layers fa-fw" role="button" onclick="clearDeviceSearch()" style="position:absolute;left:-25px;top:-15px"> <span class="fa-layers fa-fw" role="button" onclick="clearDeviceSearch()" style="position:absolute;left:-25px;top:-15px">
<i class="fa-solid fa-circle" style="color:var(--bs-secondary-bg)"></i> <i class="fa-solid fa-circle" style="color:var(--bs-secondary-bg)"></i>
@ -2818,6 +2816,8 @@
if (userinfo == null) return -1; if (userinfo == null) return -1;
var authFactorCount = 0; var authFactorCount = 0;
if (userinfo.otpsecret == 1) { authFactorCount++; } // Authenticator time factor if (userinfo.otpsecret == 1) { authFactorCount++; } // Authenticator time factor
if (userinfo.otpduo == 1) { authFactorCount++; } // Duo factor
if (userinfo.otpdev == 1) { authFactorCount++; } // Push authentication factor
if (userinfo.otphkeys > 0) { authFactorCount += userinfo.otphkeys; } // FIDO hardware factor if (userinfo.otphkeys > 0) { authFactorCount += userinfo.otphkeys; } // FIDO hardware factor
if ((features & 0x00800000) && (userinfo.otpekey == 1)) { authFactorCount++; } // EMail factor if ((features & 0x00800000) && (userinfo.otpekey == 1)) { authFactorCount++; } // EMail factor
if ((features & 0x02000000) && (features & 0x04000000) && (userinfo.phone != null)) { authFactorCount++; } // SMS factor if ((features & 0x02000000) && (features & 0x04000000) && (userinfo.phone != null)) { authFactorCount++; } // SMS factor
@ -7008,7 +7008,7 @@
function getDevicesThatMatchFilter(x) { function getDevicesThatMatchFilter(x) {
var r = []; var r = [];
var userSearch = null, ipSearch = null, groupSearch = null, tagSearch = null, agentTagSearch = null, wscSearch = null, osSearch = null, amtSearch = null, descSearch = null; var userSearch = null, ipSearch = null, groupSearch = null, tagSearch = null, agentTagSearch = null, wscSearch = null, osSearch = null, amtSearch = null, descSearch = null, connectivitySearch = null;
if (x.startsWith("user:".toLowerCase())) { userSearch = x.substring("user:".length); } if (x.startsWith("user:".toLowerCase())) { userSearch = x.substring("user:".length); }
else if (x.startsWith("u:".toLowerCase())) { userSearch = x.substring("u:".length); } else if (x.startsWith("u:".toLowerCase())) { userSearch = x.substring("u:".length); }
else if (x.startsWith("ip:".toLowerCase())) { ipSearch = x.substring("ip:".length); } else if (x.startsWith("ip:".toLowerCase())) { ipSearch = x.substring("ip:".length); }
@ -7021,6 +7021,8 @@
else if (x.startsWith("os:".toLowerCase())) { osSearch = x.substring("os:".length); } else if (x.startsWith("os:".toLowerCase())) { osSearch = x.substring("os:".length); }
else if (x.startsWith("amt:".toLowerCase())) { amtSearch = x.substring("amt:".length); } else if (x.startsWith("amt:".toLowerCase())) { amtSearch = x.substring("amt:".length); }
else if (x.startsWith("desc:".toLowerCase())) { descSearch = x.substring("desc:".length); } else if (x.startsWith("desc:".toLowerCase())) { descSearch = x.substring("desc:".length); }
else if (x.startsWith("connectivity:".toLowerCase())) { connectivitySearch = x.substring("connectivity:".length); }
else if (x.startsWith("c:".toLowerCase())) { connectivitySearch = x.substring("c:".length); }
else if (x == 'wsc:ok') { wscSearch = 1; } else if (x == 'wsc:ok') { wscSearch = 1; }
else if (x == 'wsc:noav') { wscSearch = 2; } else if (x == 'wsc:noav') { wscSearch = 2; }
else if (x == 'wsc:noupdate') { wscSearch = 3; } else if (x == 'wsc:noupdate') { wscSearch = 3; }
@ -7071,6 +7073,35 @@
else if (((wscSearch == 4) || (wscSearch == 5)) && (nodes[d].wsc.firewall != 'OK')) { r.push(d); } else if (((wscSearch == 4) || (wscSearch == 5)) && (nodes[d].wsc.firewall != 'OK')) { r.push(d); }
} }
} }
} else if (connectivitySearch != null) {
// Connectivity search
for (var d in nodes) {
if (nodes[d].conn) {
if ((nodes[d].conn & 1) != 0) {
if (nodes[d].mtype == 4) {
if ((nodes[d].porttype == 'PDU') && (connectivitySearch.toLowerCase() == 'switch')) {
r.push(d);
} else if (connectivitySearch.toLowerCase() == 'ipkvm') {
r.push(d);
}
} else if (connectivitySearch.toLowerCase() == 'agent') {
r.push(d);
}
}
if (((nodes[d].conn & 2) != 0) && (connectivitySearch.toLowerCase() == 'cira')) { r.push(d); }
else if (((nodes[d].conn & 4) != 0) && (connectivitySearch.toLowerCase() == 'amt')) { r.push(d); }
if (((nodes[d].conn & 8) != 0) && (connectivitySearch.toLowerCase() == 'relay')) { r.push(d); }
if (((nodes[d].conn & 16) != 0) && (connectivitySearch.toLowerCase() == 'mqtt')) { r.push(d); }
}
if (nodes[d].mtype == 3) {
var mesh = meshes[nodes[d].meshid];
if (mesh && mesh.relayid && (connectivitySearch.toLowerCase() == 'relay')) {
r.push(d);
} else if (mesh && (typeof mesh.relayid == 'undefined') && connectivitySearch.toLowerCase() == 'local') {
r.push(d);
}
}
}
} else if (x == '*') { } else if (x == '*') {
// Star filter // Star filter
for (var d in nodes) { if (stars[nodes[d]._id] == 1) { r.push(d); } } for (var d in nodes) { if (stars[nodes[d]._id] == 1) { r.push(d); } }
@ -10619,7 +10650,7 @@
// If shift is pressed, enter browser full screen. // If shift is pressed, enter browser full screen.
if (e.shiftKey == true) { if (e.shiftKey == true) {
enterBrowserFullscreen(Q('container')); enterBrowserFullscreen(Q('body'));
browserfullscreen = true; browserfullscreen = true;
} }
} else { } else {
@ -18733,6 +18764,9 @@
if (rec.protocol == 1) { sessionName += ' - ' + "Terminal Session"; } if (rec.protocol == 1) { sessionName += ' - ' + "Terminal Session"; }
if (rec.protocol == 2) { sessionName += ' - ' + "Desktop Session"; } if (rec.protocol == 2) { sessionName += ' - ' + "Desktop Session"; }
if (rec.protocol == 5) { sessionName += ' - ' + "File Transfer"; } if (rec.protocol == 5) { sessionName += ' - ' + "File Transfer"; }
if (rec.protocol == 6) { sessionName += ' - ' + "Admin PowerShell"; }
if (rec.protocol == 8) { sessionName += ' - ' + "User Shell"; }
if (rec.protocol == 9) { sessionName += ' - ' + "User PowerShell"; }
if (rec.protocol == 100) { sessionName += ' - ' + "Intel&reg; AMT WSMAN"; } if (rec.protocol == 100) { sessionName += ' - ' + "Intel&reg; AMT WSMAN"; }
if (rec.protocol == 101) { sessionName += ' - ' + "Intel&reg; AMT Redirection"; } if (rec.protocol == 101) { sessionName += ' - ' + "Intel&reg; AMT Redirection"; }
if (rec.protocol == 200) { sessionName += ' - ' + "Messenger"; } if (rec.protocol == 200) { sessionName += ' - ' + "Messenger"; }
@ -18763,6 +18797,9 @@
if (rec.protocol == 1) { protocolStr = "Terminal"; } if (rec.protocol == 1) { protocolStr = "Terminal"; }
if (rec.protocol == 2) { protocolStr = "Desktop"; } if (rec.protocol == 2) { protocolStr = "Desktop"; }
if (rec.protocol == 5) { protocolStr = "Files"; } if (rec.protocol == 5) { protocolStr = "Files"; }
if (rec.protocol == 6) { protocolStr = "Admin PowerShell"; }
if (rec.protocol == 8) { protocolStr = "User Shell"; }
if (rec.protocol == 9) { protocolStr = "User PowerShell"; }
if (rec.protocol == 100) { protocolStr = "Intel&reg; AMT WSMAN"; } if (rec.protocol == 100) { protocolStr = "Intel&reg; AMT WSMAN"; }
if (rec.protocol == 101) { protocolStr = "Intel&reg; AMT Redirection"; } if (rec.protocol == 101) { protocolStr = "Intel&reg; AMT Redirection"; }
if (rec.protocol == 200) { protocolStr = "Messenger"; } if (rec.protocol == 200) { protocolStr = "Messenger"; }
@ -19109,6 +19146,9 @@
if (v == 1) return "Terminal"; if (v == 1) return "Terminal";
if (v == 2) return "Desktop"; if (v == 2) return "Desktop";
if (v == 5) return "Files"; if (v == 5) return "Files";
if (v == 6) return "Admin PowerShell";
if (v == 8) return "User Shell";
if (v == 9) return "User PowerShell";
if (v == 100) return "AMT-WSMAN"; if (v == 100) return "AMT-WSMAN";
if (v == 101) return "AMT-Redir"; if (v == 101) return "AMT-Redir";
if (v == 200) return "Messenger"; if (v == 200) return "Messenger";
@ -19210,7 +19250,17 @@
if (v == 1) return "Terminal"; if (v == 1) return "Terminal";
if (v == 2) return "Desktop"; if (v == 2) return "Desktop";
if (v == 5) return "Files"; if (v == 5) return "Files";
return "Unknown"; if (v == 6) return "Admin PowerShell";
if (v == 8) return "User Shell";
if (v == 9) return "User PowerShell";
if (v == 100) return "AMT-WSMAN";
if (v == 101) return "AMT-Redir";
if (v == 200) return "Messenger";
if (v == 201) return "Web-RDP";
if (v == 202) return "Web-SSH";
if (v == 203) return "Web-SFTP";
if (v == 204) return "Web-VNC";
return "Unknown" + ' (' + v + ')';
} }
if (f == 'node') { if (f == 'node') {
var node = getNodeFromId(v); var node = getNodeFromId(v);
@ -20649,6 +20699,7 @@
if (currentNode && currentNode.links && currentNode.links[userid] && currentNode.links[userid].name != null) { return (currentNode.links[userid].name + guestname); } if (currentNode && currentNode.links && currentNode.links[userid] && currentNode.links[userid].name != null) { return (currentNode.links[userid].name + guestname); }
if (userid == userinfo._id) { return (userinfo.name + guestname); } if (userid == userinfo._id) { return (userinfo.name + guestname); }
if (nodes) { for (var a in nodes) { if (nodes[a].links) { for (var b in nodes[a].links) { if (nodes[a].links[b].name && b == userid) return (nodes[a].links[b].name + guestname); } } } } if (nodes) { for (var a in nodes) { if (nodes[a].links) { for (var b in nodes[a].links) { if (nodes[a].links[b].name && b == userid) return (nodes[a].links[b].name + guestname); } } } }
if (meshes) { for (var a in meshes) { if (meshes[a].links) { for (var b in meshes[a].links) { if (meshes[a].links[b].name && b == userid) return (meshes[a].links[b].name + guestname); } } } }
return (useridsplit[2] + guestname); return (useridsplit[2] + guestname);
} }
function round(value, precision) { var multiplier = Math.pow(10, precision || 0); return Math.round(value * multiplier) / multiplier; } function round(value, precision) { var multiplier = Math.pow(10, precision || 0); return Math.round(value * multiplier) / multiplier; }

View File

@ -401,6 +401,9 @@
var p = recFileMetadata.protocol; var p = recFileMetadata.protocol;
if (p == 1) { p = "MeshCentral Terminal"; } if (p == 1) { p = "MeshCentral Terminal"; }
else if (p == 2) { p = "MeshCentral Desktop"; } else if (p == 2) { p = "MeshCentral Desktop"; }
else if (p == 6) { p = "Admin PowerShell"; }
else if (p == 8) { p = "User Shell"; }
else if (p == 9) { p = "User PowerShell"; }
else if (p == 100) { p = "Intel&reg; AMT WSMAN"; } else if (p == 100) { p = "Intel&reg; AMT WSMAN"; }
else if (p == 101) { p = "Intel&reg; AMT Redirection"; } else if (p == 101) { p = "Intel&reg; AMT Redirection"; }
else if ((p == 102) || (p == 200 && recFileMetadata.bpp != null)) { p = "Intel&reg; AMT KVM"; } else if ((p == 102) || (p == 200 && recFileMetadata.bpp != null)) { p = "Intel&reg; AMT KVM"; }
@ -427,7 +430,7 @@
QV('TermParent', false); QV('TermParent', false);
QV('XTermParent', false); QV('XTermParent', false);
QV('ConvertAsWebM', false); QV('ConvertAsWebM', false);
if (recFileMetadata.protocol == 1) { if ((recFileMetadata.protocol == 1) || (recFileMetadata.protocol == 6) || (recFileMetadata.protocol == 8) || (recFileMetadata.protocol == 9)) {
// MeshCentral remote terminal // MeshCentral remote terminal
recFileProtocol = 1; recFileProtocol = 1;
x += '<br /><br /><span style=color:gray>' + "Press [space] to play/pause." + '</span>'; x += '<br /><br /><span style=color:gray>' + "Press [space] to play/pause." + '</span>';