From 8790e4e284b5c7be996451824e7917f3cbaf8f5d Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Tue, 30 Apr 2019 15:40:19 -0700 Subject: [PATCH] Fixed content-disposition headers. --- package.json | 2 +- redirserver.js | 2 +- webserver.js | 30 +++++++++++++++--------------- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index c6a56206..e49336a3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "meshcentral", - "version": "0.3.3-k", + "version": "0.3.3-m", "keywords": [ "Remote Management", "Intel AMT", diff --git a/redirserver.js b/redirserver.js index b1161d83..c0c5de31 100644 --- a/redirserver.js +++ b/redirserver.js @@ -58,7 +58,7 @@ module.exports.CreateRedirServer = function (parent, db, args, func) { obj.app.get("/MeshServerRootCert.cer", function (req, res) { // The redirection server starts before certificates are loaded, make sure to handle the case where no certificate is loaded now. if (obj.certificates != null) { - res.set({ "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0", "Content-Type": "application/octet-stream", "Content-Disposition": "attachment; filename=" + obj.certificates.RootName + ".cer" }); + res.set({ "Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0", "Content-Type": "application/octet-stream", "Content-Disposition": "attachment; filename=\"" + obj.certificates.RootName + ".cer\"" }); var rootcert = obj.certificates.root.cert; var i = rootcert.indexOf("-----BEGIN CERTIFICATE-----\r\n"); if (i >= 0) { rootcert = rootcert.substring(i + 29); } diff --git a/webserver.js b/webserver.js index 588890a0..f39f885f 100644 --- a/webserver.js +++ b/webserver.js @@ -1475,7 +1475,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Returns the mesh server root certificate function handleRootCertRequest(req, res) { if ((obj.userAllowedIp != null) && (checkIpAddressEx(req, res, obj.userAllowedIp, false) === false)) { return; } // Check server-wide IP filter only. - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + certificates.RootName + '.cer' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + certificates.RootName + '.cer"' }); res.send(Buffer.from(getRootCertBase64(), 'base64')); } @@ -1554,14 +1554,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (req.query.type == 1) { obj.getCiraConfigurationScript(req.query.meshid, function (script) { if (script == null) { res.sendStatus(404); } else { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=cira_setup.mescript' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="cira_setup.mescript"' }); res.send(script); } }); } else if (req.query.type == 2) { obj.getCiraCleanupScript(function (script) { if (script == null) { res.sendStatus(404); } else { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=cira_cleanup.mescript' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="cira_cleanup.mescript"' }); res.send(script); } }); @@ -2238,7 +2238,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { var argentInfo = obj.parent.meshAgentBinaries[req.query.id]; if (argentInfo == null) { res.sendStatus(404); return; } if ((req.query.meshid == null) || (argentInfo.platform != 'win32')) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + argentInfo.rname }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + argentInfo.rname + '"' }); res.sendFile(argentInfo.path); } else { // We are going to embed the .msh file into the Windows executable (signed or not). @@ -2269,14 +2269,14 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (obj.args.agentconfig) { for (var i in obj.args.agentconfig) { meshsettings += obj.args.agentconfig[i] + "\r\n"; } } if (domain.agentconfig) { for (var i in domain.agentconfig) { meshsettings += domain.agentconfig[i] + "\r\n"; } } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=' + argentInfo.rname }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="' + argentInfo.rname + '"' }); obj.parent.exeHandler.streamExeWithMeshPolicy({ platform: 'win32', sourceFileName: obj.parent.meshAgentBinaries[req.query.id].path, destinationStream: res, msh: meshsettings, peinfo: obj.parent.meshAgentBinaries[req.query.id].pe }); } } else if (req.query.script != null) { // Send a specific mesh install script back var scriptInfo = obj.parent.meshAgentInstallScripts[req.query.script]; if (scriptInfo == null) { res.sendStatus(404); return; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=' + scriptInfo.rname }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="' + scriptInfo.rname + '"' }); res.send(scriptInfo.data.split('{{{noproxy}}}').join((domain.agentnoproxy === true)?'--no-proxy ':'')); } else if (req.query.meshcmd != null) { // Send meshcmd for a specific platform back @@ -2285,17 +2285,17 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if ((agentid == 3)) { // Signed Windows MeshCmd.exe x86 var stats = null, meshCmdPath = obj.path.join(__dirname, 'agents', 'MeshCmd-signed.exe'); try { stats = obj.fs.statSync(meshCmdPath); } catch (e) { } - if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 3) ? '.exe' : '') }); res.sendFile(meshCmdPath); return; } + if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 3) ? '.exe' : '') + '"' }); res.sendFile(meshCmdPath); return; } } else if ((agentid == 4)) { // Signed Windows MeshCmd64.exe x64 var stats = null, meshCmd64Path = obj.path.join(__dirname, 'agents', 'MeshCmd64-signed.exe'); try { stats = obj.fs.statSync(meshCmd64Path); } catch (e) { } - if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') }); res.sendFile(meshCmd64Path); return; } + if ((stats != null)) { res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') + '"' }); res.sendFile(meshCmd64Path); return; } } // No signed agents, we are going to merge a new MeshCmd. if ((agentid < 10000) && (obj.parent.meshAgentBinaries[agentid + 10000] != null)) { agentid += 10000; } // Avoid merging javascript to a signed mesh agent. var argentInfo = obj.parent.meshAgentBinaries[agentid]; if ((argentInfo == null) || (obj.parent.defaultMeshCmd == null)) { res.sendStatus(404); return; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshcmd' + ((req.query.meshcmd <= 4) ? '.exe' : '') + '"' }); res.statusCode = 200; if (argentInfo.signedMeshCmdPath != null) { // If we hav a pre-signed MeshCmd, send that. @@ -2329,7 +2329,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (user != null) { meshaction.username = user.name; } var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=meshaction.txt' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="meshaction.txt"' }); res.send(JSON.stringify(meshaction, null, ' ')); }); } @@ -2344,12 +2344,12 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (user != null) { meshaction.username = user.name; } var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified if (obj.args.lanonly != true) { meshaction.serverUrl = ((obj.args.notls == true) ? 'ws://' : 'wss://') + obj.getWebServerName(domain) + ':' + httpsPort + '/' + ((domain.id == '') ? '' : ('/' + domain.id)) + 'meshrelay.ashx'; } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=meshaction.txt' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="meshaction.txt"' }); res.send(JSON.stringify(meshaction, null, ' ')); } else if (req.query.meshaction == 'winrouter') { var p = obj.path.join(__dirname, 'agents', 'MeshCentralRouter.exe'); if (obj.fs.existsSync(p)) { - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename=MeshCentralRouter.exe' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/plain', 'Content-Disposition': 'attachment; filename="MeshCentralRouter.exe"' }); try { res.sendFile(p); } catch (e) { res.sendStatus(404); } } else { res.sendStatus(404); } } else { @@ -2420,7 +2420,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { // Setup the response output var archive = require('archiver')('zip', { level: 5 }); // Sets the compression method. archive.on('error', function (err) { throw err; }); - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename=MeshAgent-' + mesh.name + '.zip' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/zip', 'Content-Disposition': 'attachment; filename="MeshAgent-' + mesh.name + '.zip"' }); archive.pipe(res); // Opens the "MeshAgentOSXPackager.zip" @@ -2501,7 +2501,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (obj.args.agentconfig) { for (var i in obj.args.agentconfig) { meshsettings += obj.args.agentconfig[i] + "\r\n"; } } if (domain.agentconfig) { for (var i in domain.agentconfig) { meshsettings += domain.agentconfig[i] + "\r\n"; } } - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename=meshagent.msh' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'application/octet-stream', 'Content-Disposition': 'attachment; filename="meshagent.msh"' }); res.send(meshsettings); }; @@ -2526,7 +2526,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) { if (rights == 0) { res.sendStatus(401); return; } // Get the list of power events and send them - res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename=powerevents.csv' }); + res.set({ 'Cache-Control': 'no-cache, no-store, must-revalidate', 'Pragma': 'no-cache', 'Expires': '0', 'Content-Type': 'text/csv', 'Content-Disposition': 'attachment; filename="powerevents.csv"' }); obj.db.getPowerTimeline(node._id, function (err, docs) { var xevents = [ 'Time, State, Previous State' ], prevState = 0; for (var i in docs) {