diff --git a/meshcentral.js b/meshcentral.js index e3e2ffd1..a9d3389a 100644 --- a/meshcentral.js +++ b/meshcentral.js @@ -1443,9 +1443,6 @@ function CreateMeshCentralServer(config, args) { } } - // Update proxy certificates - if (obj.supportsProxyCertificatesRequest == true) { obj.updateProxyCertificates(true); } - // Load CloudFlare trusted proxies list if needed if ((obj.config.settings.trustedproxy != null) && (typeof obj.config.settings.trustedproxy == 'string') && (obj.config.settings.trustedproxy.toLowerCase() == 'cloudflare')) { obj.config.settings.extrascriptsrc = 'ajax.cloudflare.com'; // Add CloudFlare as a trusted script source. This allows for CloudFlare's RocketLoader feature. @@ -1536,6 +1533,9 @@ function CreateMeshCentralServer(config, args) { obj.webserver = require('./webserver.js').CreateWebServer(obj, obj.db, obj.args, obj.certificates); if (obj.redirserver != null) { obj.redirserver.hookMainWebServer(obj.certificates); } + // Update proxy certificates + if (obj.supportsProxyCertificatesRequest == true) { obj.updateProxyCertificates(true); } + // Setup the Intel AMT event handler obj.amtEventHandler = require('./amtevents.js').CreateAmtEventsHandler(obj); @@ -1789,8 +1789,10 @@ function CreateMeshCentralServer(config, args) { // Decode a RSA certificate and hash the public key, if this is not RSA, skip this. var forgeCert = obj.certificateOperations.forge.pki.certificateFromAsn1(obj.certificateOperations.forge.asn1.fromDer(cert)); xdomain.certkeyhash = obj.certificateOperations.forge.pki.getPublicKeyFingerprint(forgeCert.publicKey, { md: obj.certificateOperations.forge.md.sha384.create(), encoding: 'hex' }); + obj.webserver.webCertificateExpire[xdomain.id] = Date.parse(forgeCert.validity.notAfter); // Update certificate expire time //console.log('V1: ' + xdomain.certkeyhash); } catch (ex) { + delete obj.webserver.webCertificateExpire[xdomain.id]; // Remove certificate expire time delete xdomain.certkeyhash; } diff --git a/meshuser.js b/meshuser.js index 5a9c8885..2e28eaf0 100644 --- a/meshuser.js +++ b/meshuser.js @@ -495,6 +495,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use if (user.siteadmin === SITERIGHT_ADMIN) { if (parent.parent.config.settings.managealldevicegroups.indexOf(user._id) >= 0) { serverinfo.manageAllDeviceGroups = true; } if (obj.crossDomain === true) { serverinfo.crossDomain = []; for (var i in parent.parent.config.domains) { serverinfo.crossDomain.push(i); } } + if (typeof parent.webCertificateExpire[domain.id] == 'number') { serverinfo.certExpire = parent.webCertificateExpire[domain.id]; } } if (typeof domain.terminal == 'object') { // Settings used for remote terminal feature if ((typeof domain.terminal.linuxshell == 'string') && (domain.terminal.linuxshell != 'any')) { serverinfo.linuxshell = domain.terminal.linuxshell; } @@ -904,7 +905,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use switch (cmd) { case 'help': { - var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager,amtpasswords'; + var fin = '', f = '', availcommands = 'help,maintenance,info,versions,resetserver,usersessions,closeusersessions,tasklimiter,setmaxtasks,cores,migrationagents,agentstats,agentissues,webstats,mpsstats,swarmstats,acceleratorsstats,updatecheck,serverupdate,nodeconfig,heapdump,relays,autobackup,backupconfig,dupagents,dispatchtable,badlogins,showpaths,le,lecheck,leevents,dbstats,dbcounters,sms,amtacm,certhashes,watchdog,amtmanager,amtpasswords,certexpire'; if (parent.parent.config.settings.heapdump === true) { availcommands += ',heapdump'; } availcommands = availcommands.split(',').sort(); while (availcommands.length > 0) { if (f.length > 80) { fin += (f + ',\r\n'); f = ''; } f += (((f != '') ? ', ' : ' ') + availcommands.shift()); } @@ -925,6 +926,14 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use } break; } + case 'certexpire': { + const now = Date.now(); + for (var i in parent.webCertificateExpire) { + const domainName = (i == '') ? '[Default]' : i; + r += domainName + ', expires in ' + Math.floor((parent.webCertificateExpire[i] - now) / 86400000) + ' day(s)\r\n'; + } + break; + } case 'webpush': { if (parent.parent.webpush == null) { r = "Web push not supported."; diff --git a/public/styles/style.css b/public/styles/style.css index 4f05e38b..024f9239 100644 --- a/public/styles/style.css +++ b/public/styles/style.css @@ -1024,7 +1024,7 @@ NoMeshesPanel img { padding-left: 15px; } -#p2noMeshFound, #serverStats, #serverWarnings { +#p2noMeshFound, #serverStats, #serverWarnings, #serverCertWarnings { margin-left: 40px; } diff --git a/views/default-mobile.handlebars b/views/default-mobile.handlebars index 7f65f37f..48a6bb19 100644 --- a/views/default-mobile.handlebars +++ b/views/default-mobile.handlebars @@ -1398,6 +1398,12 @@ serverinfo = message.serverinfo; if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); } if (userinfo != null) updateSelf(); + if (serverinfo.certExpire != null) { + var days = Math.floor((serverinfo.certExpire - Date.now()) / 86400000); + if ((days >= 0) && (days < 20)) { + addNotification({ text: format("Certificate expires in {0} day(s)", days) }); + } + } break; } case 'authcookie': { diff --git a/views/default.handlebars b/views/default.handlebars index be95fc1e..64303116 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -525,6 +525,7 @@
@@ -2138,6 +2139,14 @@ if (serverinfo.timeout) { setInterval(checkIdleSessionTimeout, 10000); checkIdleSessionTimeout(); } if (debugmode == 1) { console.log('Server time: ', printDateTime(new Date(serverinfo.serverTime))); } setupServiceWorker(); + if (serverinfo.certExpire != null) { + var days = Math.floor((serverinfo.certExpire - Date.now()) / 86400000); + if ((days >= 0) && (days < 20)) { + QH('serverCertWarnings', '