From 4b5b516eb8edb8c47f1931b65f067c8bbfecfe12 Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Wed, 10 Jan 2018 21:47:35 +0900 Subject: [PATCH 1/5] Sturdier approveDomains logic Making approveDomains sturdier for following cases: - Former logic didn't work if `config.hostname` was a subdomain (or a sub-subdomain). example: `service.mydomain.com` - Former logic used a `..-.`. - Former logic accepted all subdomains in `per-user` mode, no matter if the user existed or not. (`userRecord` can be `null`) - Former logic was written in `return-first-on-success` code logic order. This is written in `return-first-on-error` making it easier to read. --- index.js | 55 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/index.js b/index.js index fa7466d..cebfdcf 100644 --- a/index.js +++ b/index.js @@ -326,42 +326,45 @@ function addConfigHelpers (config) { } function approveDomains (config, cloud) { + var domainReg + // Dots in domains are normal but dots in a regexp would be replaced with "any character" + var regHost = config.hostName.replace(/\./g, '\\.') + if (config.sites === 'per-archive') { + domainReg = new RegExp(`^(([^-]+)\-([^.]+)\\.)?${regHost}$`, 'g') + } else if (config.sites === 'per-user') { + domainReg = new RegExp(`^(()([^.]+)\\.)?${regHost}$`, 'g') + } else { + domainReg = new RegExp(`^${regHost}$`, 'g') + } return async (options, certs, cb) => { var {domain} = options options.agreeTos = true options.email = config.letsencrypt.email - // toplevel domain? - if (domain === config.hostname) { - return cb(null, {options, certs}) + var domainParts = domainReg.exec(domain) + if (!domainParts) { + return cb(new Error('invalid domain')) } - - // try looking up the site + var archiveName = domainParts[2] + var userName = domainParts[3] + try { - var archiveName - var userName - var domainParts = domain.split('.') - if (config.sites === 'per-user') { - // make sure the user record exists - userName = domainParts[0] - await cloud.usersDB.getByUsername(userName) - return cb(null, {options, certs}) - } else if (config.sites === 'per-archive') { - // make sure the user and archive records exists - if (domainParts.length === 3) { - userName = archiveName = domainParts[0] - } else { - archiveName = domainParts[0] - userName = domainParts[1] + if (userName) { + var userRecord = await cloud.usersDB.getByUsername(userName) + if (!userRecord) { + return cb(new Error(`${userName} is not a user`)) } - let userRecord = await cloud.usersDB.getByUsername(userName) - let archiveRecord = userRecord.archives.find(a => a.name === archiveName) - if (archiveRecord) { - return cb(null, {options, certs}) + if (archiveName) { + var archiveRecord = userRecord.archives.find(a => a.name === archiveName) + if (!archiveRecord) { + return cb(new Error(`Archive ${archiveName} for user ${userName} not found!`)) + } } } - } catch (e) {} - cb(new Error('Invalid domain')) + } catch (e) { + return cb(e) + } + cb(null, {options, certs}) } } From 0e02cdd4c2c31d7b2dc0a4b90b10d26a3887e547 Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Wed, 10 Jan 2018 21:57:22 +0900 Subject: [PATCH 2/5] Allowing any domain if hostname is missing Mostly useful for tests. --- index.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index cebfdcf..75cdc05 100644 --- a/index.js +++ b/index.js @@ -327,14 +327,19 @@ function addConfigHelpers (config) { function approveDomains (config, cloud) { var domainReg - // Dots in domains are normal but dots in a regexp would be replaced with "any character" - var regHost = config.hostName.replace(/\./g, '\\.') - if (config.sites === 'per-archive') { - domainReg = new RegExp(`^(([^-]+)\-([^.]+)\\.)?${regHost}$`, 'g') - } else if (config.sites === 'per-user') { - domainReg = new RegExp(`^(()([^.]+)\\.)?${regHost}$`, 'g') + if (config.hostname) { + // Dots in domains are normal but dots in a regexp would be replaced with "any character" + var regHost = (config.hostName || '').replace(/\./g, '\\.') + if (config.sites === 'per-archive') { + domainReg = new RegExp(`^(([^-]+)\-([^.]+)\\.)?${regHost}$`, 'g') + } else if (config.sites === 'per-user') { + domainReg = new RegExp(`^(()([^.]+)\\.)?${regHost}$`, 'g') + } else { + domainReg = new RegExp(`^${regHost}$`, 'g') + } } else { - domainReg = new RegExp(`^${regHost}$`, 'g') + // Allow any domain + domainReg = /.?/g } return async (options, certs, cb) => { var {domain} = options From dbd243d8997d82f0bce348293cc76d26d5cc52c5 Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Wed, 10 Jan 2018 22:01:59 +0900 Subject: [PATCH 3/5] Linting --- index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/index.js b/index.js index 75cdc05..55546a6 100644 --- a/index.js +++ b/index.js @@ -331,7 +331,7 @@ function approveDomains (config, cloud) { // Dots in domains are normal but dots in a regexp would be replaced with "any character" var regHost = (config.hostName || '').replace(/\./g, '\\.') if (config.sites === 'per-archive') { - domainReg = new RegExp(`^(([^-]+)\-([^.]+)\\.)?${regHost}$`, 'g') + domainReg = new RegExp(`^(([^-]+)-([^.]+)\\.)?${regHost}$`, 'g') } else if (config.sites === 'per-user') { domainReg = new RegExp(`^(()([^.]+)\\.)?${regHost}$`, 'g') } else { @@ -352,7 +352,7 @@ function approveDomains (config, cloud) { } var archiveName = domainParts[2] var userName = domainParts[3] - + try { if (userName) { var userRecord = await cloud.usersDB.getByUsername(userName) From 84cbc66c64bef5e47348cba2348a5b9a857f1f66 Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Wed, 10 Jan 2018 22:04:34 +0900 Subject: [PATCH 4/5] Allowing - in archive names Didn't know that -'s are allowed in archive names :sweat: --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 55546a6..9e13433 100644 --- a/index.js +++ b/index.js @@ -331,7 +331,7 @@ function approveDomains (config, cloud) { // Dots in domains are normal but dots in a regexp would be replaced with "any character" var regHost = (config.hostName || '').replace(/\./g, '\\.') if (config.sites === 'per-archive') { - domainReg = new RegExp(`^(([^-]+)-([^.]+)\\.)?${regHost}$`, 'g') + domainReg = new RegExp(`^((.+)-([^.]+)\\.)?${regHost}$`, 'g') } else if (config.sites === 'per-user') { domainReg = new RegExp(`^(()([^.]+)\\.)?${regHost}$`, 'g') } else { From 2ea04f9cbbf061db74f78edf15135ab69d72692f Mon Sep 17 00:00:00 2001 From: Martin Heidegger Date: Tue, 13 Feb 2018 13:43:53 +0900 Subject: [PATCH 5/5] Typo in using the hostname --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index 9e13433..fded66f 100644 --- a/index.js +++ b/index.js @@ -329,7 +329,7 @@ function approveDomains (config, cloud) { var domainReg if (config.hostname) { // Dots in domains are normal but dots in a regexp would be replaced with "any character" - var regHost = (config.hostName || '').replace(/\./g, '\\.') + var regHost = (config.hostname || '').replace(/\./g, '\\.') if (config.sites === 'per-archive') { domainReg = new RegExp(`^((.+)-([^.]+)\\.)?${regHost}$`, 'g') } else if (config.sites === 'per-user') {