diff --git a/MeshCentralServer.njsproj b/MeshCentralServer.njsproj index 395682c9..4aacbfe3 100644 --- a/MeshCentralServer.njsproj +++ b/MeshCentralServer.njsproj @@ -173,7 +173,6 @@ - @@ -215,12 +214,18 @@ + + + + + + diff --git a/agents/meshcore.js b/agents/meshcore.js index de15348a..5813bb90 100644 --- a/agents/meshcore.js +++ b/agents/meshcore.js @@ -1012,7 +1012,7 @@ function createMeshCore(agent) { try { switch (process.platform) { case 'win32': - //child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ["/c", "start", url], { type: childProcess.SpawnTypes.USER, uid: require('user-sessions').Current().Active[0].SessionId }); // TODO: Using user-session breaks Win7 + //child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ["/c", "start", url], { type: childProcess.SpawnTypes.USER, uid: require('user-sessions').Current().Active[0].SessionId }); child = require('child_process').execFile(process.env['windir'] + '\\system32\\cmd.exe', ["/c", "start", url], { type: childProcess.SpawnTypes.USER }); break; case 'linux': @@ -1061,7 +1061,7 @@ function createMeshCore(agent) { } case 'users': { if (meshCoreObj.users == null) { response = 'Active users are unknown.'; } else { response = 'Active Users: ' + meshCoreObj.users.join(', ') + '.'; } - //require('user-sessions').enumerateUsers().then(function (u) { for (var i in u) { sendConsoleText(u[i]); } }); + require('user-sessions').enumerateUsers().then(function (u) { for (var i in u) { sendConsoleText(u[i]); } }); break; } case 'toast': { @@ -1597,7 +1597,6 @@ function createMeshCore(agent) { } catch (e) { amtLmsState = -1; amtLms = null; } // Setup logged in user monitoring (THIS IS BROKEN IN WIN7) - /* try { var userSession = require('user-sessions'); userSession.on('changed', function onUserSessionChanged() { @@ -1615,7 +1614,6 @@ function createMeshCore(agent) { //userSession.on('locked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has LOCKED the desktop'); }); //userSession.on('unlocked', function (user) { sendConsoleText('[' + (user.Domain ? user.Domain + '\\' : '') + user.Username + '] has UNLOCKED the desktop'); }); } catch (ex) { } - */ } obj.stop = function () { diff --git a/agents/modules_meshcore/user-sessions.js b/agents/modules_meshcore/user-sessions.js index f882fb7c..c0c3b5bc 100644 --- a/agents/modules_meshcore/user-sessions.js +++ b/agents/modules_meshcore/user-sessions.js @@ -93,7 +93,7 @@ function UserSessions() } this._user32 = this._marshal.CreateNativeProxy('user32.dll'); - this._user32.CreateMethod('RegisterPowerSettingNotification'); + this._user32.CreateMethod({ method: 'RegisterPowerSettingNotification', threadDispatch: 1 }); this._user32.CreateMethod('UnregisterPowerSettingNotification'); this._rpcrt = this._marshal.CreateNativeProxy('Rpcrt4.dll'); this._rpcrt.CreateMethod('UuidFromStringA'); diff --git a/certoperations.js b/certoperations.js index 8dbb830f..b0c4c57d 100644 --- a/certoperations.js +++ b/certoperations.js @@ -151,7 +151,7 @@ module.exports.CertificateOperations = function () { var certargs = args.cert; var mpscertargs = args.mpscert; var strongCertificate = (args.fastcert ? false : true); - var rcountmax = 5; + var rcountmax = 4; var caindex = 1; var caok = false; var calist = []; @@ -197,12 +197,6 @@ module.exports.CertificateOperations = function () { rcount++; } - // If the console certificate already exist, load it - if (obj.fileExists(parent.getConfigFilePath("amtconsole-cert-public.crt")) && obj.fileExists(parent.getConfigFilePath("agentserver-cert-private.key"))) { - r.console = { cert: obj.fs.readFileSync(parent.getConfigFilePath("amtconsole-cert-public.crt"), "utf8"), key: obj.fs.readFileSync(parent.getConfigFilePath("amtconsole-cert-private.key"), "utf8") }; - rcount++; - } - // If the swarm server certificate exist, load it (This is an optional certificate) if (obj.fileExists(parent.getConfigFilePath("swarmserver-cert-public.crt")) && obj.fileExists(parent.getConfigFilePath("swarmserver-cert-private.key"))) { r.swarmserver = { cert: obj.fs.readFileSync(parent.getConfigFilePath("swarmserver-cert-public.crt"), "utf8"), key: obj.fs.readFileSync(parent.getConfigFilePath("swarmserver-cert-private.key"), "utf8") }; @@ -285,8 +279,6 @@ module.exports.CertificateOperations = function () { } if (rcount === rcountmax) { - // Fetch the Intel AMT console name - r.AmtConsoleName = obj.pki.certificateFromPem(r.console.cert).subject.getField("CN").value; // Fetch the Intel AMT MPS common name r.AmtMpsName = obj.pki.certificateFromPem(r.mps.cert).subject.getField("CN").value; // Fetch the name of the server @@ -396,24 +388,7 @@ module.exports.CertificateOperations = function () { mpsPrivateKey = r.mps.key; } - // If the Intel AMT console certificate does not exist, create one - var consoleCertAndKey, consoleCertificate, consolePrivateKey, amtConsoleName = "MeshCentral"; - if (r.console == null) { - console.log("Generating Intel AMT console certificate..."); - consoleCertAndKey = obj.IssueWebServerCertificate(rootCertAndKey, false, amtConsoleName, country, organization, { name: "extKeyUsage", clientAuth: true, "2.16.840.1.113741.1.2.1": true, "2.16.840.1.113741.1.2.2": true, "2.16.840.1.113741.1.2.3": true }, false); // Intel AMT Remote, Agent and Activation usages - consoleCertificate = obj.pki.certificateToPem(consoleCertAndKey.cert); - consolePrivateKey = obj.pki.privateKeyToPem(consoleCertAndKey.key); - obj.fs.writeFileSync(parent.getConfigFilePath("amtconsole-cert-public.crt"), consoleCertificate); - obj.fs.writeFileSync(parent.getConfigFilePath("amtconsole-cert-private.key"), consolePrivateKey); - } else { - // Keep the console certificate we have - consoleCertAndKey = { cert: obj.pki.certificateFromPem(r.console.cert), key: obj.pki.privateKeyFromPem(r.console.key) }; - consoleCertificate = r.console.cert; - consolePrivateKey = r.console.key; - amtConsoleName = consoleCertAndKey.cert.subject.getField("CN").value; - } - - r = { root: { cert: rootCertificate, key: rootPrivateKey }, web: { cert: webCertificate, key: webPrivateKey, ca: [] }, mps: { cert: mpsCertificate, key: mpsPrivateKey }, agent: { cert: agentCertificate, key: agentPrivateKey }, console: { cert: consoleCertificate, key: consolePrivateKey }, ca: calist, CommonName: commonName, RootName: rootName, AmtConsoleName: amtConsoleName, AmtMpsName: mpsCommonName, dns: {}, WebIssuer: webIssuer }; + r = { root: { cert: rootCertificate, key: rootPrivateKey }, web: { cert: webCertificate, key: webPrivateKey, ca: [] }, mps: { cert: mpsCertificate, key: mpsPrivateKey }, agent: { cert: agentCertificate, key: agentPrivateKey }, ca: calist, CommonName: commonName, RootName: rootName, AmtMpsName: mpsCommonName, dns: {}, WebIssuer: webIssuer }; // Look for domains with DNS names that have no certificates and generated them. for (i in config.domains) { diff --git a/letsEncrypt.js b/letsEncrypt.js index 789ad12c..7d4395d8 100644 --- a/letsEncrypt.js +++ b/letsEncrypt.js @@ -78,8 +78,18 @@ module.exports.CreateLetsEncrypt = function (parent) { obj.leResults = results; // If we already have real certificates, use them. - if (results.altnames.indexOf(certs.CommonName) >= 0) { certs.web.cert = results.cert; certs.web.key = results.privkey; certs.web.ca = [results.chain]; } - for (var i in obj.parent.config.domains) { if ((obj.parent.config.domains[i].dns != null) && (results.altnames.indexOf(obj.parent.config.domains[i].dns) >= 0)) { certs.dns[i].cert = results.cert; certs.dns[i].key = results.privkey; certs.dns[i].ca = [results.chain]; } } + if (results.altnames.indexOf(certs.CommonName) >= 0) { + certs.web.cert = results.cert; + certs.web.key = results.privkey; + certs.web.ca = [results.chain]; + } + for (var i in obj.parent.config.domains) { + if ((obj.parent.config.domains[i].dns != null) && (results.altnames.indexOf(obj.parent.config.domains[i].dns) >= 0)) { + certs.dns[i].cert = results.cert; + certs.dns[i].key = results.privkey; + certs.dns[i].ca = [results.chain]; + } + } func(certs); // Check if the Let's Encrypt certificate needs to be renewed. diff --git a/meshuser.js b/meshuser.js index 3caa6079..7c720979 100644 --- a/meshuser.js +++ b/meshuser.js @@ -632,7 +632,7 @@ module.exports.CreateMeshUser = function (parent, db, ws, req, args, domain, use var httpsPort = ((obj.parent.args.aliasport == null) ? obj.parent.args.port : obj.parent.args.aliasport); // Use HTTPS alias port is specified var xdomain = (domain.dns == null) ? domain.id : ''; if (xdomain != '') xdomain += "/"; - var url = "http" + (obj.args.notls ? '' : 's') + "://" + obj.parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger.htm?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name); + var url = "http" + (obj.args.notls ? '' : 's') + "://" + obj.parent.getWebServerName(domain) + ":" + httpsPort + "/" + xdomain + "messenger?id=meshmessenger/" + encodeURIComponent(command.nodeid) + "/" + encodeURIComponent(user._id) + "&title=" + encodeURIComponent(user.name); // Create the notification message routeCommandToNode({ "action": "openUrl", "nodeid": command.nodeid, "userid": user._id, "username": user.name, "url": url }); diff --git a/package.json b/package.json index 93b9f60a..907961e3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.2.4-t", + "version": "0.2.4-y", "keywords": [ "Remote Management", "Intel AMT", diff --git a/public/compress.bat b/public/compress.bat index fb06b4f8..e984870a 100644 --- a/public/compress.bat +++ b/public/compress.bat @@ -31,4 +31,11 @@ COPY ..\views\login-mobile.handlebars index.html ..\..\WebSiteCompiler\bin\Debug\WebSiteCompiler.exe compress.wcc -c COPY compress.htm ..\views\login-mobile-min.handlebars DEL compress.htm +DEL index.html + +REM *** messenger.handlebars +COPY ..\views\messenger.handlebars index.html +..\..\WebSiteCompiler\bin\Debug\WebSiteCompiler.exe compress.wcc -c +COPY compress.htm ..\views\messenger-min.handlebars +DEL compress.htm DEL index.html \ No newline at end of file diff --git a/public/scripts/agent-redir-ws-0.1.0.js b/public/scripts/agent-redir-ws-0.1.0.js index 935d7523..ef7cf0e5 100644 --- a/public/scripts/agent-redir-ws-0.1.0.js +++ b/public/scripts/agent-redir-ws-0.1.0.js @@ -107,7 +107,7 @@ var CreateAgentRedirect = function (meshserver, module, serverPublicNamePort) { } obj.webrtc.oniceconnectionstatechange = function () { if (obj.webrtc != null) { - if (obj.webrtc.iceConnectionState == 'disconnected') { obj.Stop(); } + if (obj.webrtc.iceConnectionState == 'disconnected') { if (obj.webRtcActive == true) { obj.Stop(); } else { obj.xxCloseWebRTC(); } } else if (obj.webrtc.iceConnectionState == 'failed') { obj.xxCloseWebRTC(); } } } diff --git a/public/scripts/filesaver.js b/public/scripts/filesaver.js new file mode 100644 index 00000000..f5048b58 --- /dev/null +++ b/public/scripts/filesaver.js @@ -0,0 +1,180 @@ +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define([], factory); + } else if (typeof exports !== "undefined") { + factory(); + } else { + var mod = { + exports: {} + }; + factory(); + global.FileSaver = mod.exports; + } +})(this, function () { + "use strict"; + + /* + * FileSaver.js + * A saveAs() FileSaver implementation. + * + * By Eli Grey, http://eligrey.com + * + * License : https://github.com/eligrey/FileSaver.js/blob/master/LICENSE.md (MIT) + * source : http://purl.eligrey.com/github/FileSaver.js + */ + // The one and only way of getting global scope in all environments + // https://stackoverflow.com/q/3277182/1008999 + var _global = typeof window === 'object' && window.window === window ? window : typeof self === 'object' && self.self === self ? self : typeof global === 'object' && global.global === global ? global : void 0; + + function bom(blob, opts) { + if (typeof opts === 'undefined') opts = { + autoBom: false + };else if (typeof opts !== 'object') { + console.warn('Depricated: Expected third argument to be a object'); + opts = { + autoBom: !opts + }; + } // prepend BOM for UTF-8 XML and text/* types (including HTML) + // note: your browser will automatically convert UTF-16 U+FEFF to EF BB BF + + if (opts.autoBom && /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(blob.type)) { + return new Blob([String.fromCharCode(0xFEFF), blob], { + type: blob.type + }); + } + + return blob; + } + + function download(url, name, opts) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', url); + xhr.responseType = 'blob'; + + xhr.onload = function () { + saveAs(xhr.response, name, opts); + }; + + xhr.onerror = function () { + console.error('could not download file'); + }; + + xhr.send(); + } + + function corsEnabled(url) { + var xhr = new XMLHttpRequest(); // use sync to avoid popup blocker + + xhr.open('HEAD', url, false); + xhr.send(); + return xhr.status >= 200 && xhr.status <= 299; + } // `a.click()` doesn't work for all browsers (#465) + + + function click(node) { + try { + node.dispatchEvent(new MouseEvent('click')); + } catch (e) { + var evt = document.createEvent('MouseEvents'); + evt.initMouseEvent('click', true, true, window, 0, 0, 0, 80, 20, false, false, false, false, 0, null); + node.dispatchEvent(evt); + } + } + + var saveAs = _global.saveAs || // probably in some web worker + typeof window !== 'object' || window !== _global ? function saveAs() {} + /* noop */ + // Use download attribute first if possible (#193 Lumia mobile) + : 'download' in HTMLAnchorElement.prototype ? function saveAs(blob, name, opts) { + var URL = _global.URL || _global.webkitURL; + var a = document.createElement('a'); + name = name || blob.name || 'download'; + a.download = name; + a.rel = 'noopener'; // tabnabbing + // TODO: detect chrome extensions & packaged apps + // a.target = '_blank' + + if (typeof blob === 'string') { + // Support regular links + a.href = blob; + + if (a.origin !== location.origin) { + corsEnabled(a.href) ? download(blob, name, opts) : click(a, a.target = '_blank'); + } else { + click(a); + } + } else { + // Support blobs + a.href = URL.createObjectURL(blob); + setTimeout(function () { + URL.revokeObjectURL(a.href); + }, 4E4); // 40s + + setTimeout(function () { + click(a); + }, 0); + } + } // Use msSaveOrOpenBlob as a second approach + : 'msSaveOrOpenBlob' in navigator ? function saveAs(blob, name, opts) { + name = name || blob.name || 'download'; + + if (typeof blob === 'string') { + if (corsEnabled(blob)) { + download(blob, name, opts); + } else { + var a = document.createElement('a'); + a.href = blob; + a.target = '_blank'; + setTimeout(function () { + click(a); + }); + } + } else { + navigator.msSaveOrOpenBlob(bom(blob, opts), name); + } + } // Fallback to using FileReader and a popup + : function saveAs(blob, name, opts, popup) { + // Open a popup immediately do go around popup blocker + // Mostly only avalible on user interaction and the fileReader is async so... + popup = popup || open('', '_blank'); + + if (popup) { + popup.document.title = popup.document.body.innerText = 'downloading...'; + } + + if (typeof blob === 'string') return download(blob, name, opts); + var force = blob.type === 'application/octet-stream'; + + var isSafari = /constructor/i.test(_global.HTMLElement) || _global.safari; + + var isChromeIOS = /CriOS\/[\d]+/.test(navigator.userAgent); + + if ((isChromeIOS || force && isSafari) && typeof FileReader === 'object') { + // Safari doesn't allow downloading of blob urls + var reader = new FileReader(); + + reader.onloadend = function () { + var url = reader.result; + url = isChromeIOS ? url : url.replace(/^data:[^;]*;/, 'data:attachment/file;'); + if (popup) popup.location.href = url;else location = url; + popup = null; // reverse-tabnabbing #460 + }; + + reader.readAsDataURL(blob); + } else { + var URL = _global.URL || _global.webkitURL; + var url = URL.createObjectURL(blob); + if (popup) popup.location = url;else location.href = url; + popup = null; // reverse-tabnabbing #460 + + setTimeout(function () { + URL.revokeObjectURL(url); + }, 4E4); // 40s + } + }; + _global.saveAs = saveAs.saveAs = saveAs; + + if (typeof module !== 'undefined') { + module.exports = saveAs; + } +}); diff --git a/public/scripts/filesaver.min.js b/public/scripts/filesaver.min.js new file mode 100644 index 00000000..66e1e3eb --- /dev/null +++ b/public/scripts/filesaver.min.js @@ -0,0 +1,3 @@ +(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Depricated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(b,c,d){var e=new XMLHttpRequest;e.open("GET",b),e.responseType="blob",e.onload=function(){a(e.response,c,d)},e.onerror=function(){console.error("could not download file")},e.send()}function d(a){var b=new XMLHttpRequest;return b.open("HEAD",a,!1),b.send(),200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=f.saveAs||"object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(a,b,d,e){if(e=e||open("","_blank"),e&&(e.document.title=e.document.body.innerText="downloading..."),"string"==typeof a)return c(a,b,d);var g="application/octet-stream"===a.type,h=/constructor/i.test(f.HTMLElement)||f.safari,i=/CriOS\/[\d]+/.test(navigator.userAgent);if((i||g&&h)&&"object"==typeof FileReader){var j=new FileReader;j.onloadend=function(){var a=j.result;a=i?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),e?e.location.href=a:location=a,e=null},j.readAsDataURL(a)}else{var k=f.URL||f.webkitURL,l=k.createObjectURL(a);e?e.location=l:location.href=l,e=null,setTimeout(function(){k.revokeObjectURL(l)},4E4)}};f.saveAs=a.saveAs=a,"undefined"!=typeof module&&(module.exports=a)}); + +//# sourceMappingURL=FileSaver.min.js.map \ No newline at end of file diff --git a/public/styles/messenger.css b/public/styles/messenger.css index 8cd23720..bf044de7 100644 --- a/public/styles/messenger.css +++ b/public/styles/messenger.css @@ -2,6 +2,7 @@ cursor: pointer; border: none; margin: 2px; + margin-top: 3px; float: right; border-radius: 3px; height: 32px; diff --git a/sample-config.json b/sample-config.json index b9fd5e1e..8847ef00 100644 --- a/sample-config.json +++ b/sample-config.json @@ -18,7 +18,8 @@ "_UserAllowedIP": "127.0.0.1,::1,192.168.0.100", "_LocalDiscovery": { "name": "Local server name", "info": "Information about this server" }, "_TlsOffload": true, - "_MpsTlsOffload": true + "_MpsTlsOffload": true, + "_WebRtConfig": { "iceServers": [ { "urls": "stun:stun.services.mozilla.com" }, { "urls": "stun:stun.l.google.com:19302" } ] } }, "_domains": { "": { diff --git a/views/default-min.handlebars b/views/default-min.handlebars index faabd322..3eb86de2 100644 --- a/views/default-min.handlebars +++ b/views/default-min.handlebars @@ -1 +1 @@ - MeshCentral
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file + MeshCentral
{{{title}}}
{{{title2}}}

{{{logoutControl}}}

 

\ No newline at end of file diff --git a/views/default-mobile-min.handlebars b/views/default-mobile-min.handlebars index 11211530..34fc01e0 100644 --- a/views/default-mobile-min.handlebars +++ b/views/default-mobile-min.handlebars @@ -1 +1 @@ - MeshCentral - Login
{{{title}}}
{{{title2}}}
\ No newline at end of file + MeshCentral - Login
{{{title}}}
{{{title2}}}
\ No newline at end of file diff --git a/views/default.handlebars b/views/default.handlebars index 1c87b564..148dc4e0 100644 --- a/views/default.handlebars +++ b/views/default.handlebars @@ -447,11 +447,10 @@
  -   - - - + + +
\ No newline at end of file diff --git a/public/messenger.htm b/views/messenger.handlebars similarity index 85% rename from public/messenger.htm rename to views/messenger.handlebars index 793d5b39..c946dab6 100644 --- a/public/messenger.htm +++ b/views/messenger.handlebars @@ -8,7 +8,7 @@ - +
@@ -38,17 +38,25 @@
- diff --git a/webserver.js b/webserver.js index 21f315b2..e17ef3a1 100644 --- a/webserver.js +++ b/webserver.js @@ -656,6 +656,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((domain.sspi != null) && ((req.query.login == null) || (obj.parent.loginCookieEncryptionKey == null))) { // Login using SSPI domain.sspi.authenticate(req, res, function (err) { if ((err != null) || (req.connection.user == null)) { res.end('Authentication Required...'); } else { handleRootRequestEx(req, res, domain); } }); + } else if (req.query.user && req.query.pass) { + // User credentials are being passed in the URL. WARNING: Putting credentials in a URL is not good security... but people are requesting this option. + var userid = 'user/' + domain.id + '/' + req.query.user.toLowerCase(); + if (obj.users[userid] != null) { + obj.authenticate(req.query.user, req.query.pass, domain, function (err, userid) { + req.session.userid = userid; + req.session.domainid = domain.id; + req.session.currentNode = ''; + handleRootRequestEx(req, res, domain); + }); + } } else { // Login using a different system handleRootRequestEx(req, res, domain); @@ -813,7 +824,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { return ''; } - // Renter the terms of service. + // Render the terms of service. function handleTermsRequest(req, res) { var domain = checkUserIpAddress(req, res); if (domain == null) return; @@ -847,6 +858,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { } } + // Render the messenger application. + function handleMessengerRequest(req, res) { + var webRtcConfig = null; + if (obj.parent.config.settings && obj.parent.config.settings.webrtconfig && (typeof obj.parent.config.settings.webrtconfig == 'object')) { webRtcConfig = encodeURIComponent(JSON.stringify(obj.parent.config.settings.webrtconfig)); } + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0' }); + res.render(obj.path.join(__dirname, 'views/messenger'), { webrtconfig: webRtcConfig }); + } + // Returns the server root certificate encoded in base64 function getRootCertBase64() { var rootcert = obj.certificates.root.cert; @@ -1188,7 +1207,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // TLSSocket to encapsulate TLS communication, which then tunneled via SerialTunnel an then wrapped through CIRA APF var TLSSocket = require('tls').TLSSocket; - var tlsoptions = { secureProtocol: ((req.query.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false, cert: obj.certificates.console.cert, key: obj.certificates.console.key }; + var tlsoptions = { secureProtocol: ((req.query.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; var tlsock = new TLSSocket(ser, tlsoptions); tlsock.on('error', function (err) { Debug(1, "CIRA TLS Connection Error ", err); }); tlsock.on('secureConnect', function () { Debug(2, "CIRA Secure TLS Connection"); ws._socket.resume(); }); @@ -1301,7 +1320,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { ws._socket.resume(); } else { // If TLS is going to be used, setup a TLS socket - var tlsoptions = { secureProtocol: ((req.query.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false, cert: obj.certificates.console.cert, key: obj.certificates.console.key }; + var tlsoptions = { secureProtocol: ((req.query.tls1only == 1) ? 'TLSv1_method' : 'SSLv23_method'), ciphers: 'RSA+AES:!aNULL:!MD5:!DSS', secureOptions: obj.constants.SSL_OP_NO_SSLv2 | obj.constants.SSL_OP_NO_SSLv3 | obj.constants.SSL_OP_NO_COMPRESSION | obj.constants.SSL_OP_CIPHER_SERVER_PREFERENCE, rejectUnauthorized: false }; ws.forwardclient = obj.tls.connect(port, node.host, tlsoptions, function () { // The TLS connection method is the same as TCP, but located a bit differently. Debug(2, 'TLS connected to ' + node.host + ':' + port + '.'); @@ -1843,6 +1862,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { obj.app.get(url + 'checkmail', handleCheckMailRequest); obj.app.post(url + 'amtevents.ashx', obj.handleAmtEventRequest); obj.app.get(url + 'meshagents', obj.handleMeshAgentRequest); + obj.app.get(url + 'messenger', handleMessengerRequest); obj.app.get(url + 'meshosxagent', obj.handleMeshOsxAgentRequest); obj.app.get(url + 'meshsettings', obj.handleMeshSettingsRequest); obj.app.get(url + 'downloadfile.ashx', handleDownloadFile);