diff options
author | cel <cel@lOUVT+Phkvai9a/cCS/RKo+S9hnPAQdVixms/7ldpPA=.ed25519> | 2020-03-28 15:27:10 -0400 |
---|---|---|
committer | cel <cel@lOUVT+Phkvai9a/cCS/RKo+S9hnPAQdVixms/7ldpPA=.ed25519> | 2020-04-10 16:11:50 -0400 |
commit | 5a719f74ab1963f17275e28ae0aa9779b4b1ec03 (patch) | |
tree | cd897362837591a6ef434fa5fe119cd20e663ae0 /lib | |
parent | c87ebee6a707d1031fedf2247b440e6aab04332d (diff) | |
download | patchfoo-5a719f74ab1963f17275e28ae0aa9779b4b1ec03.tar.gz patchfoo-5a719f74ab1963f17275e28ae0aa9779b4b1ec03.zip |
Restrict access based on Host header
Diffstat (limited to 'lib')
-rw-r--r-- | lib/app.js | 37 | ||||
-rw-r--r-- | lib/serve.js | 6 |
2 files changed, 42 insertions, 1 deletions
@@ -35,6 +35,7 @@ function getKey(msg) { } function App(sbot, config) { + var self = this this.sbot = sbot this.config = config @@ -55,11 +56,31 @@ function App(sbot, config) { this.voteBranches = !!config.voteBranches this.copyableIds = config.copyableIds == null ? true : config.copyableIds - this.hostname = (/:/.test(this.host) ? '[' + this.host + ']' : this.host) + this.port + this.hostname = (/:/.test(this.host) ? '[' + this.host + ']' : this.host) + ':' + this.port this.dir = path.join(config.path, conf.dir || 'patchfoo') this.scriptDir = path.join(this.dir, conf.scriptDir || 'script') this.draftsDir = path.join(this.dir, conf.draftsDir || 'drafts') + this.allowHosts = u.toArray(conf.allowHosts || + ['localhost:', '127.0.0.1:', '[::1]:', this.hostname]) + this.allowHostsParsed = this.allowHosts.indexOf('*') > -1 ? [{ + subdomains: true, + host: '', + port: '*' + }] : this.allowHosts.map(function (hostname) { + var m = /^(\.)?(.*?)(:([0-9]*?|\*))?$/.exec(hostname) + if (!m) return void console.trace('Unable to parse hostname pattern "'+hostname+'"') + var port = !m[3] ? 80 : + !m[4] ? Number(self.port) : + '*' === m[4] ? '*' : Number(m[4]) + if (port !== '*' && isNaN(port)) return void console.trace('Unable to parse port in hostname pattern "'+hostname+'". Default port: "'+self.port+'"') + return { + subdomains: !!m[1], + host: m[2], + port: port + } + }).filter(Boolean) + var base = conf.base || '/' this.opts = { base: base, @@ -117,6 +138,20 @@ function App(sbot, config) { ] } +App.prototype.isAllowedHostHeader = function (hostname) { + var m = /^(\[[^\]]+\]|[^:]+)(?::([0-9]+))?/.exec(hostname) + if (!m) return void console.error('Unable to parse Host header "'+hostname+'"') + var host = m[1], port = Number(m[2] || 80) + for (var i = 0; i < this.allowHostsParsed.length; i++) { + var allow = this.allowHostsParsed[i] + if ((allow.port === '*' || allow.port === port) + && (allow.host === '' || allow.host === host || + (allow.subdomains && host.endsWith('.'+allow.host))) + ) return true + } + return false +} + App.prototype.go = function () { var self = this var server = http.createServer(function (req, res) { diff --git a/lib/serve.js b/lib/serve.js index c3e2115..fdf24f7 100644 --- a/lib/serve.js +++ b/lib/serve.js @@ -112,6 +112,12 @@ Serve.prototype.go = function () { } } + if (!this.app.isAllowedHostHeader(this.req.headers.host)) { + console.error('Host header not allowed: "' + this.req.headers.host + '"') + this.res.writeHead(403) + return this.res.end('Forbidden') + } + this.replyMentionFeeds = conf.replyMentionFeeds == null ? true : Boolean(conf.replyMentionFeeds) |