diff --git a/common.js b/common.js
index 2db7f60b..bac385b6 100644
--- a/common.js
+++ b/common.js
@@ -128,10 +128,11 @@ module.exports.escapeHtml = function (string) { return String(string).replace(/[
module.exports.escapeHtmlBreaks = function (string) { return String(string).replace(/[&<>"'`=\/]/g, function (s) { return { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''', '/': '/', '`': '`', '=': '=', '\r': '
', '\n': '' }[s]; }); };
// Lowercase all the names in a object recursively
-module.exports.objKeysToLower = function (obj) {
+// Allow for exception keys, child of exceptions will not get lower-cased.
+module.exports.objKeysToLower = function (obj, exceptions) {
for (var i in obj) {
if (i.toLowerCase() !== i) { obj[i.toLowerCase()] = obj[i]; delete obj[i]; } // LowerCase all key names
- if (typeof obj[i] == 'object') { module.exports.objKeysToLower(obj[i]); } // LowerCase all key names in the child object
+ if ((typeof obj[i] == 'object') && ((exceptions == null) || (exceptions.indexOf(i.toLowerCase()) == -1))) { module.exports.objKeysToLower(obj[i], exceptions); } // LowerCase all key names in the child object
}
return obj;
};
diff --git a/meshcentral.js b/meshcentral.js
index 7584a7bc..dbe2bc60 100644
--- a/meshcentral.js
+++ b/meshcentral.js
@@ -479,7 +479,7 @@ function CreateMeshCentralServer(config, args) {
// Lower case all keys in the config file
try {
- require('./common.js').objKeysToLower(config2);
+ require('./common.js').objKeysToLower(config2, ["ldapoptions"]);
} catch (ex) {
console.log('CRITICAL ERROR: Unable to access the file \"./common.js\".\r\nCheck folder & file permissions.');
process.exit();
@@ -543,8 +543,9 @@ function CreateMeshCentralServer(config, args) {
if (obj.config.domains[''].dns != null) { console.log("ERROR: Default domain can't have a DNS name."); return; }
var xdomains = {}; for (i in obj.config.domains) { if (obj.config.domains[i].title == null) { obj.config.domains[i].title = 'MeshCentral'; } if (obj.config.domains[i].title2 == null) { obj.config.domains[i].title2 = '2.0 Beta 2'; } xdomains[i.toLowerCase()] = obj.config.domains[i]; } obj.config.domains = xdomains;
var bannedDomains = ['public', 'private', 'images', 'scripts', 'styles', 'views']; // List of banned domains
- for (i in obj.config.domains) { for (var j in bannedDomains) { if (i == bannedDomains[j]) { console.log("ERROR: Domain '" + i + "' is not allowed domain name in ./data/config.json."); return; } } }
+ for (i in obj.config.domains) { for (var j in bannedDomains) { if (i == bannedDomains[j]) { console.log("ERROR: Domain '" + i + "' is not allowed domain name in config.json."); return; } } }
for (i in obj.config.domains) {
+ if (typeof config.domains[i].auth == 'string') { config.domains[i].auth = config.domains[i].auth.toLowerCase(); }
if (obj.config.domains[i].limits == null) { obj.config.domains[i].limits = {}; }
if (obj.config.domains[i].dns == null) { obj.config.domains[i].url = (i == '') ? '/' : ('/' + i + '/'); } else { obj.config.domains[i].url = '/'; }
obj.config.domains[i].id = i;
@@ -552,6 +553,11 @@ function CreateMeshCentralServer(config, args) {
if (typeof obj.config.domains[i].userblockedip == 'string') { if (obj.config.domains[i].userblockedip == '') { obj.config.domains[i].userblockedip = null; } else { obj.config.domains[i].userblockedip = obj.config.domains[i].userallowedip.split(','); } }
if (typeof obj.config.domains[i].agentallowedip == 'string') { if (obj.config.domains[i].agentallowedip == '') { obj.config.domains[i].agentallowedip = null; } else { obj.config.domains[i].agentallowedip = obj.config.domains[i].agentallowedip.split(','); } }
if (typeof obj.config.domains[i].agentblockedip == 'string') { if (obj.config.domains[i].agentblockedip == '') { obj.config.domains[i].agentblockedip = null; } else { obj.config.domains[i].agentblockedip = obj.config.domains[i].agentblockedip.split(','); } }
+ if ((obj.config.domains[i].auth == 'ldap') && (typeof obj.config.domains[i].ldapoptions != 'object')) {
+ if (i == '') { console.log("ERROR: Default domain is LDAP, but is missing LDAPOptions."); } else { console.log("ERROR: Domain '" + i + "' is LDAP, but is missing LDAPOptions."); }
+ process.exit();
+ return;
+ }
}
// Log passed arguments into Windows Service Log
@@ -1618,11 +1624,12 @@ function getConfig(createSampleConfig) {
// Lower case all keys in the config file
try {
- require('./common.js').objKeysToLower(config);
+ require('./common.js').objKeysToLower(config, ["ldapoptions"]);
} catch (ex) {
console.log('CRITICAL ERROR: Unable to access the file \"./common.js\".\r\nCheck folder & file permissions.');
process.exit();
}
+
return config;
}
@@ -1680,16 +1687,24 @@ function mainStart(args) {
var config = getConfig(false);
if (config == null) { process.exit(); }
+ // Lowercase the auth value is present
+ for (var i in config.domains) { if (typeof config.domains[i].auth == 'string') { config.domains[i].auth = config.domains[i].auth.toLowerCase(); } }
+
// Check is Windows SSPI and YubiKey OTP will be used
var sspi = false;
+ var ldap = false;
var allsspi = true;
var yubikey = false;
if (require('os').platform() == 'win32') { for (var i in config.domains) { if (config.domains[i].auth == 'sspi') { sspi = true; } else { allsspi = false; } } } else { allsspi = false; }
- for (var i in config.domains) { if (config.domains[i].yubikey != null) { yubikey = true; } }
+ for (var i in config.domains) {
+ if (config.domains[i].yubikey != null) { yubikey = true; }
+ if (config.domains[i].auth == 'ldap') { ldap = true; }
+ }
// Build the list of required modules
var modules = ['ws', 'nedb', 'https', 'yauzl', 'xmldom', 'express', 'archiver', 'multiparty', 'node-forge', 'express-ws', 'compression', 'body-parser', 'connect-redis', 'express-handlebars'];
if (require('os').platform() == 'win32') { modules.push('node-windows'); if (sspi == true) { modules.push('node-sspi'); } } // Add Windows modules
+ if (ldap == true) { modules.push('ldapauth-fork'); }
if (config.letsencrypt != null) { modules.push('greenlock'); modules.push('le-store-certbot'); modules.push('le-challenge-fs'); modules.push('le-acme-core'); } // Add Greenlock Modules
if (config.settings.mongodb != null) { modules.push('mongojs'); } // Add MongoDB
if (config.smtp != null) { modules.push('nodemailer'); } // Add SMTP support
diff --git a/meshuser.js b/meshuser.js
index d659f457..1248dc41 100644
--- a/meshuser.js
+++ b/meshuser.js
@@ -251,7 +251,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
var httpport = ((args.aliasport != null) ? args.aliasport : args.port);
// Build server information object
- var serverinfo = { name: parent.certificates.CommonName, mpsname: parent.certificates.AmtMpsName, mpsport: mpsport, mpspass: args.mpspass, port: httpport, emailcheck: ((parent.parent.mailserver != null) && (domain.auth != 'sspi')), domainauth: (domain.auth == 'sspi') };
+ var serverinfo = { name: parent.certificates.CommonName, mpsname: parent.certificates.AmtMpsName, mpsport: mpsport, mpspass: args.mpspass, port: httpport, emailcheck: ((parent.parent.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap')), domainauth: ((domain.auth == 'sspi') || (domain.auth == 'ldap')) };
if (args.notls == true) { serverinfo.https = false; } else { serverinfo.https = true; serverinfo.redirport = args.redirport; }
// Send server information
@@ -715,7 +715,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
case 'changeemail':
{
// Change the email address
- if (domain.auth == 'sspi') return;
+ if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) return;
if (common.validateEmail(command.email, 1, 256) == false) return;
if (parent.users[req.session.userid].email != command.email) {
// Check if this email is already validated on a different account
@@ -740,7 +740,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
parent.parent.DispatchEvent(['*', 'server-users', user._id], obj, message);
// Send the verification email
- if ((parent.parent.mailserver != null) && (domain.auth != 'sspi')) { parent.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); }
+ if (parent.parent.mailserver != null) { parent.parent.mailserver.sendAccountCheckMail(domain, user.name, user.email); }
}
});
}
@@ -749,7 +749,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
case 'verifyemail':
{
// Send a account email verification email
- if (domain.auth == 'sspi') return;
+ if ((domain.auth == 'sspi') || (domain.auth == 'ldap')) return;
if (common.validateString(command.email, 3, 1024) == false) return;
if ((parent.parent.mailserver != null) && (parent.users[req.session.userid].email == command.email)) {
// Send the verification email
@@ -1069,7 +1069,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use
if ((user.siteadmin != 0xFFFFFFFF) && ((user.siteadmin & 64) != 0)) break;
// In some situations, we need a verified email address to create a device group.
- if ((parent.parent.mailserver != null) && (domain.auth != 'sspi') && (user.emailVerified !== true) && (user.siteadmin != 0xFFFFFFFF)) return; // User must verify it's email first.
+ if ((parent.parent.mailserver != null) && (domain.auth != 'sspi') && (domain.auth != 'ldap') && (user.emailVerified !== true) && (user.siteadmin != 0xFFFFFFFF)) return; // User must verify it's email first.
// Create mesh
if (common.validateString(command.meshname, 1, 64) == false) break; // Meshname is between 1 and 64 characters
diff --git a/package.json b/package.json
index 41c0bb0d..83a01954 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"express-handlebars": "^3.0.0",
"express-ws": "^4.0.0",
"ipcheck": "^0.1.0",
+ "ldapauth-fork": "^4.2.0",
"meshcentral": "*",
"minimist": "^1.2.0",
"multiparty": "^4.2.1",
diff --git a/views/default-min.handlebars b/views/default-min.handlebars
index 6a8ead42..280d7e91 100644
--- a/views/default-min.handlebars
+++ b/views/default-min.handlebars
@@ -1 +1 @@
-
{{{logoutControl}}}
My Devices | My Account | My Events | My Files | My Users | My Server |
{{{logoutControl}}}
My Devices | My Account | My Events | My Files | My Users | My Server |