More FIDO2 fixes.

Ylian Saint-Hilaire committed Mar 25, 2019 at 14:43 UTC b8a0512f839dabd0ae51abf3ec97f72ffa0acc79
4 files changed +36 -28
package.json
+1 -1
@@ -1,6 +1,6 @@
1 {
2 "name": "meshcentral",
3 - "version": "0.3.0-y",
3 + "version": "0.3.0-z",
4 "keywords": [
5 "Remote Management",
6 "Intel AMT",
views/login-mobile.handlebars
+1 -1
@@ -260,7 +260,7 @@
260 var passRequirements = "{{{passRequirements}}}";
261 if (passRequirements != "") { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
262 var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
263 - var hardwareKeyChallenge = '{{{hkey}}}';
263 + var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
264 var currentpanel = 0;
265
266 function startup() {
views/login.handlebars
+2 -2
@@ -110,7 +110,7 @@
110 <div id="welcomeText" style="display:none">Connect to your home or office devices from anywhere in the world using <a href="http://www.meshcommander.com/meshcentral2">MeshCentral</a>, the real time, open source remote monitoring and management web site. You will need to download and install a management agent on your computers. Once installed, computers will show up in the &quot;My Devices&quot; section of this web site and you will be able to monitor them and take control of them.</div>
111 <table id="centralTable" style=width:100%>
112 <tr>
113 - <td id="welcomeimage" align="right">
113 + <td id="welcomeimage" align="right" style="display:none">
114 <picture>
115 <img alt="" width=359 height=310 src=welcome.jpg />
116 </picture>
@@ -332,7 +332,7 @@
332 var newAccountPass = parseInt('{{{newAccountPass}}}');
333 var emailCheck = ('{{{emailcheck}}}' == 'true');
334 var passRequirements = "{{{passRequirements}}}";
335 - var hardwareKeyChallenge = '{{{hkey}}}';
335 + var hardwareKeyChallenge = decodeURIComponent('{{{hkey}}}');
336 if (passRequirements != "") { passRequirements = JSON.parse(decodeURIComponent(passRequirements)); } else { passRequirements = {}; }
337 var passRequirementsEx = ((passRequirements.min != null) || (passRequirements.max != null) || (passRequirements.upper != null) || (passRequirements.lower != null) || (passRequirements.numeric != null) || (passRequirements.nonalpha != null));
338 var features = parseInt('{{{features}}}');
webserver.js
+32 -24
@@ -396,7 +396,11 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
396 for (var i = 0; i < user.otphkeys.length; i++) { if (user.otphkeys[i].type == 1) { u2fKeys.push(user.otphkeys[i]); } }
397 if (u2fKeys.length > 0) {
398 // Check authentication response
399 - require('authdog').finishAuthentication(req.session.u2fchallenge, authResponse, u2fKeys).then(function (authenticationStatus) { func(true); }, function (error) { func(false); });
399 + var authdoglib = null;
400 + try { authdoglib = require('authdog'); } catch (ex) { }
401 + if (authdoglib == null) { func(false); } else {
402 + authdoglib.finishAuthentication(req.session.u2fchallenge, authResponse, u2fKeys).then(function (authenticationStatus) { func(true); }, function (error) { console.log(error); func(false); });
403 + }
404 return;
405 }
406 }
@@ -458,24 +462,28 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
462 }
463 }
464
461 - // Get all U2F keys
462 - var u2fKeys = [];
463 - for (var i = 0; i < user.otphkeys.length; i++) { if (user.otphkeys[i].type == 1) { u2fKeys.push(user.otphkeys[i]); } }
464 -
465 - // Generate a U2F challenge
466 - if (u2fKeys.length > 0) {
467 - require('authdog').startAuthentication('https://' + obj.parent.certificates.CommonName, u2fKeys, { requestId: 0, timeoutSeconds: 60 }).then(function (registrationRequest) {
468 - // Save authentication request to session for later use
469 - req.session.u2fchallenge = registrationRequest;
470 -
471 - // Send authentication request to client
472 - func(JSON.stringify(registrationRequest));
473 - }, function (error) {
474 - // Handle authentication request error
465 + var authdoglib = null;
466 + try { authdoglib = require('authdog'); } catch (ex) { }
467 + if (authdoglib != null) {
468 + // Get all U2F keys
469 + var u2fKeys = [];
470 + for (var i = 0; i < user.otphkeys.length; i++) { if (user.otphkeys[i].type == 1) { u2fKeys.push(user.otphkeys[i]); } }
471 +
472 + // Generate a U2F challenge
473 + if (u2fKeys.length > 0) {
474 + authdoglib.startAuthentication('https://' + obj.parent.certificates.CommonName, u2fKeys, { requestId: 0, timeoutSeconds: 60 }).then(function (registrationRequest) {
475 + // Save authentication request to session for later use
476 + req.session.u2fchallenge = registrationRequest;
477 +
478 + // Send authentication request to client
479 + func(JSON.stringify(registrationRequest));
480 + }, function (error) {
481 + // Handle authentication request error
482 + func('');
483 + });
484 + } else {
485 func('');
476 - });
477 - } else {
478 - func('');
486 + }
487 }
488 } else {
489 func('');
@@ -1187,9 +1195,9 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1195 // If this is a 2 factor auth request, look for a hardware key challenge.
1196 // Normal login 2 factor request
1197 if ((req.session.loginmode == '4') && (req.session.tokenusername)) {
1190 - var user = obj.users['user/' + domain.id + '/' + req.session.tokenusername];
1198 + var user = obj.users['user/' + domain.id + '/' + req.session.tokenusername.toLowerCase()];
1199 if (user != null) {
1192 - getHardwareKeyChallenge(req, domain, user, function (u2fChallenge) { handleRootRequestLogin(req, res, domain, u2fChallenge, passRequirements); });
1200 + getHardwareKeyChallenge(req, domain, user, function (hwchallenge) { handleRootRequestLogin(req, res, domain, hwchallenge, passRequirements); });
1201 return;
1202 }
1203 }
@@ -1202,7 +1210,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1210 } else {
1211 var user = obj.users[docs[0]._id];
1212 if (user != null) {
1205 - getHardwareKeyChallenge(req, domain, user, function (u2fChallenge) { handleRootRequestLogin(req, res, domain, u2fChallenge, passRequirements); });
1213 + getHardwareKeyChallenge(req, domain, user, function (hwchallenge) { handleRootRequestLogin(req, res, domain, hwchallenge, passRequirements); });
1214 } else {
1215 req.session = null;
1216 res.redirect(domain.url);
@@ -1240,14 +1248,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
1248 if (obj.args.minify && !req.query.nominify) {
1249 // Try to server the minified version if we can.
1250 try {
1243 - res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile-min' : 'login-min'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: hardwareKeyChallenge, message: message, passhint: passhint, welcometext: domain.welcometext?encodeURIComponent(domain.welcometext):null });
1251 + res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile-min' : 'login-min'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge), message: message, passhint: passhint, welcometext: domain.welcometext?encodeURIComponent(domain.welcometext):null });
1252 } catch (ex) {
1253 // In case of an exception, serve the non-minified version.
1246 - res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile' : 'login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: hardwareKeyChallenge, message: message, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext) : null });
1254 + res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile' : 'login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge), message: message, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext) : null });
1255 }
1256 } else {
1257 // Serve non-minified version of web pages.
1250 - res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile' : 'login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: hardwareKeyChallenge, message: message, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext) : null });
1258 + res.render(obj.path.join(obj.parent.webViewsPath, isMobileBrowser(req) ? 'login-mobile' : 'login'), { loginmode: loginmode, rootCertLink: getRootCertLink(), title: domain.title, title2: domain.title2, newAccount: domain.newaccounts, newAccountPass: (((domain.newaccountspass == null) || (domain.newaccountspass == '')) ? 0 : 1), serverDnsName: obj.getWebServerName(domain), serverPublicPort: httpsPort, emailcheck: emailcheck, features: features, sessiontime: args.sessiontime, passRequirements: passRequirements, footer: (domain.footer == null) ? '' : domain.footer, hkey: encodeURIComponent(hardwareKeyChallenge), message: message, passhint: passhint, welcometext: domain.welcometext ? encodeURIComponent(domain.welcometext) : null });
1259 }
1260
1261 /*