diff --git a/lib/www/server/api/middleware/auth/authentify.js b/lib/www/server/api/middleware/auth/authentify.js index e79a111..bd75486 100644 --- a/lib/www/server/api/middleware/auth/authentify.js +++ b/lib/www/server/api/middleware/auth/authentify.js @@ -2,16 +2,23 @@ const dns = require('dns'); const { Netmask } = require('netmask'); const cfg = require('../../../lib/config'); const jwt = require('../../../lib/jwt'); +const user = require('../../../lib/db/user'); async function authorisedIP (req, res) { - const validIPs = cfg._("global.users.login.ip") || {}; - for (const key in validIPs) { - const block = new Netmask(key); + const validIPs = await user.ip({active: true}); // Get all active IP logins + validIPs.forEach( i => i.$block = new Netmask(i.ip) ); + validIPs.sort( (a, b) => b.$block.bitmask - a.$block.netmask ); // More specific IPs have precedence + for (const ip of validIPs) { + const block = ip.$block; if (block.contains(req.ip)) { - const payload = Object.assign({ + const payload = { + ...ip, ip: req.ip, autologin: true - }, validIPs[key]); + }; + delete payload.$block; + delete payload.hash; + delete payload.active; jwt.issue(payload, req, res); return true; } @@ -20,7 +27,7 @@ async function authorisedIP (req, res) { } async function authorisedHost (req, res) { - const validHosts = cfg._("global.users.login.host") || {}; + const validHosts = await user.host({active: true}); // Get all active host logins for (const key in validHosts) { try { const ip = await dns.promises.resolve(key); @@ -42,6 +49,17 @@ async function authorisedHost (req, res) { return false; } +// TODO: Check client TLS certificates +// Probably will do this via Nginx with +// ssl_verify_client optional; +// and then putting either of the +// $ssl_client_s_dn or $ssl_client_escaped_cert +// variables into an HTTP header for Node +// to check (naturally, it must be ensured +// that a user cannot just insert the header +// in a request). + + async function auth (req, res, next) { if (res.headersSent) { diff --git a/lib/www/server/lib/db/user/index.js b/lib/www/server/lib/db/user/index.js new file mode 100644 index 0000000..2a54c7d --- /dev/null +++ b/lib/www/server/lib/db/user/index.js @@ -0,0 +1,60 @@ +const { pool } = require('../connection'); + +const IPUser = Symbol("IPUser"); +const HostUser = Symbol("HostUser"); +const NamedUser = Symbol("NamedUser"); + +async function userOfType(type, opts = {}) { + opts = {active: true, ...opts}; + + let propertyName; + switch (type) { + case IPUser: + propertyName = "ip"; + break; + case HostUser: + propertyName = "host"; + break; + case NamedUser: + propertyName = "hash"; + break; + } + + if (propertyName) { + + const text = ` + SELECT * + FROM keystore + WHERE type = 'user' AND data ? $1 + `; + + const res = await pool.query(text, [ propertyName ]); + + const users = res.rows.map( row => ({ + ...row.data, + id: row.key, + hash: undefined + }) ).filter( row => opts.active == null || opts.active === row.active ); + + return users; + + } +} + +async function ip (opts = {}) { + return await userOfType(IPUser, opts); +} + +async function host (opts = {}) { + return await userOfType(HostUser, opts); +} + +async function named (opts = {}) { + return await userOfType(NamedUser, opts); +} + +module.exports = { + ip, + host, + named +}