From e7d07692703aa8a52bb0ddac1935fc19b299ac28 Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Sat, 21 Feb 2015 01:16:38 +0000 Subject: [PATCH] fix ssl bugs, account for proxyable apps --- lib/vhost-sni-server.js | 80 ++++++++++++++++++++++++----------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/lib/vhost-sni-server.js b/lib/vhost-sni-server.js index 2cd0774..c4059dd 100644 --- a/lib/vhost-sni-server.js +++ b/lib/vhost-sni-server.js @@ -150,7 +150,12 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { if (localApp.create) { // TODO read local config.yml and pass it in // TODO pass in websocket - localApp = localApp.create(/*config*/); + localApp = localApp.create(secureServer, { + dummyCerts: dummyCerts + , hostname: domaininfo.hostname + , port: securePort + , url: domaininfo.pathname + }); if (!localApp) { return getDummyAppContext(null, "[ERROR] no app was returned by app.js for " + domaininfo.driname); } @@ -174,7 +179,12 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { function loadDomainVhosts() { domainMerged.forEach(function (domainApp) { - console.log('[log] loaded mounts for domain ' + domainApp.hostname); + if (domainApp._loaded) { + return; + } + + console.log('[log] [once] Loading mounts for ' + domainApp.hostname); + domainApp._loaded = true; app.use(vhost(domainApp.hostname, domainApp.apps)); app.use(vhost('www.' + domainApp.hostname, domainApp.apps)); }); @@ -185,6 +195,7 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { var vhost = (req.headers.host || '').split(':')[0]; // the matching domain didn't catch it + console.log('[log] vhost:', vhost); if (domainMergeMap[vhost]) { next(); return; @@ -199,13 +210,15 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { return forEachAsync(domainMergeMap[vhost].apps, function (fn) { return new PromiseA(function (resolve) { + function next(err) { + if (err) { + reject(err); + } + resolve(); + } + try { - fn(req, res, function (err) { - if (err) { - reject(err); - } - resolve(); - }); + fn(req, res, next); } catch(e) { reject(e); } @@ -229,7 +242,8 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { // return forEachAsync(rootDomains, loadCerts); // TODO load these even more lazily return forEachAsync(readNewVhosts(), loadDomainMounts).then(loadDomainVhosts).then(function () { - app.use(hotloadApp); + console.log('[log] TODO fix and use hotload'); + //app.use(hotloadApp); resolve(app); return; }); @@ -269,55 +283,48 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { } try { - secureContexts[domainname] = createSecureContext(secOpts).context; + secureContexts[domainname] = createSecureContext(secOpts); } catch(err) { console.error("[ERROR] Certificates in '" + certsPath + "' could not be used:"); console.error(err); return null; } + if (!secureContexts[domainname]) { + console.error("[ERROR] Sanity check fail, no cert for '" + domainname + "'"); + return null; + } + return secureContexts[domainname]; } function createSecureServer() { - var dummyCerts = loadDummyCerts(); + var localDummyCerts = loadDummyCerts(); var secureOpts = { // fallback / default dummy certs - key: dummyCerts.key - , cert: dummyCerts.cert - , ca: dummyCerts.ca + key: localDummyCerts.key + , cert: localDummyCerts.cert + , ca: localDummyCerts.ca }; function addSniWorkaroundCallback() { //SNICallback is passed the domain name, see NodeJS docs on TLS secureOpts.SNICallback = function (domainname, cb) { - console.log('[log] SNI:', domainname); - if (!secureContexts.dummy) { - secureContexts.dummy = createSecureContext(dummyCerts); + console.log('[log] Loading dummy certs'); + secureContexts.dummy = createSecureContext(localDummyCerts); } - var secureContext = secureContexts[domainname] - || loadCerts(domainname) - || secureContexts.dummy - //|| createSecureContext(dummyCerts) - //|| createSecureContext(loadDummyCerts()) - ; - - if (!secureContext) { - // testing with shared dummy - //secureContext = secureContexts.dummy; - // testing passing bad argument - //secureContext = createSecureContext(loadDummyCerts); - // testing with fresh dummy - secureContext = createSecureContext(loadDummyCerts()); + if (!secureContexts[domainname]) { + console.log('[log] Loading certs for', domainname); + secureContexts[domainname] = loadCerts(domainname); } // workaround for v0.12 / v1.2 backwards compat bug if ('function' === typeof cb) { - cb(null, secureContext); + cb(null, secureContexts[domainname] || secureContexts.dummy); } else { - return secureContext; + return secureContexts[domainname] || secureContexts.dummy; } }; } @@ -346,6 +353,13 @@ module.exports.create = function (securePort, certsPath, vhostsdir) { // Get up and listening as absolutely quickly as possible secureServer.on('request', function (req, res) { + if (/(^|\.)_proxyable\./.test(req.headers.host)) { + // device-id-12345678._proxyable.myapp.mydomain.com => myapp.mydomain.com + // _proxyable.myapp.mydomain.com => myapp.mydomain.com + // TODO myapp.mydomain.com.proxyable.com => myapp.mydomain.com + req.headers.host = req.headers.host.replace(/.*\.?_proxyable\./, ''); + } + loadPromise().then(function (app) { app(req, res); });