diff --git a/code/config.json b/code/config.json deleted file mode 100644 index c1f207f..0000000 --- a/code/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "ports": { - "radius_authentication": 1812, - "radius_accounting": 1813 - }, - "client_secret": "password", - "storage": "json:./data.json", - "default_vlan_enabled": true, - "default_vlan_id": 90, - "mac_auth_only": true -} diff --git a/code/data.json b/code/data.json index ef0372d..095a1ee 100644 --- a/code/data.json +++ b/code/data.json @@ -9,11 +9,6 @@ "username": "AB:CD:EF:12:34:56", "password": "AB:CD:EF:12:34:56", "vlan": "123" - }, - { - "username": "abcdef123456", - "password": "abcdef123456", - "vlan": "123" } ] } \ No newline at end of file diff --git a/code/lib/data.js b/code/lib/data.js index 0c55441..e995e8f 100644 --- a/code/lib/data.js +++ b/code/lib/data.js @@ -1,4 +1,5 @@ const fs = require ('fs'); +const timeauth = require ('./time.js'); try { var data = JSON.parse (fs.readFileSync ('./data.json').toString ()); @@ -19,7 +20,9 @@ const persistData = () => { content.users.push ({ username: user, password: users[user].password, - vlan: users[user].vlan + vlan: users[user].vlan, + description: users[user].description, + rules: users[user].rules }); }); fs.writeFileSync ('./data.json', JSON.stringify (content, null, 2)); @@ -29,7 +32,9 @@ users = {}; data.users.forEach ((e) => { users[e.username] = { password: e.password, - vlan: e.vlan + vlan: e.vlan, + description: e.description, + rules: e.rules } }); @@ -40,9 +45,16 @@ module.exports = { password = password.toLowerCase ().replace (/[:-]/g, ''); } if (users[username] && users[username].password == password) { - return { - vlan: users[username].vlan - }; + // Check time + var rules = users[username].rules || []; + if (timeauth.checkAuth (rules)) { + return { + vlan: users[username].vlan + }; + } + else { + return false; + } } else { return false; @@ -59,11 +71,13 @@ module.exports = { password = password.toLowerCase ().replace (/[:-]/g, ''); } var description = payload.description || ""; + var rules = payload.rules || []; var vlan = payload.vlan; users[username] = { password: password, vlan: vlan, - description: description + description: description, + rules: rules }; persistData (); callback ("OK\n\n", null); diff --git a/code/lib/time.js b/code/lib/time.js new file mode 100644 index 0000000..7ba7d13 --- /dev/null +++ b/code/lib/time.js @@ -0,0 +1,80 @@ +const rangeStringToArray = (str) => { + // Split the string by hyphen + const parts = str.split ("-"); + // Validate input format (two numbers separated by hyphen) + if (parts.length !== 2 || isNaN (parts[0]) || isNaN (parts[1])) { + return null; // Return null for invalid format + } + // Convert strings to numbers + const start = parseInt (parts[0], 10); + const end = parseInt (parts[1], 10); + // Check if start is less than or equal to end (inclusive range) + if (start > end) { + return null; // Return null for invalid range + } + // Use Array.from() to create an array with sequence + return Array.from ({ length: end - start + 1 }, (_, i) => start + i); +}; + +const resolveRange = (str) => { + const numberSets = str.split (","); // Split by commas + const numbers = []; + for (const set of numberSets) { + // Check if it's a range + if (set.includes ("-")) { + const range = rangeStringToArray (set); // Use the previous function + if (range) { + numbers.push(...range); // Spread operator to add elements from range array + } + else { + const num = parseInt(set, 10); + // Check if conversion is successful (valid number) + if (!isNaN(num)) { + numbers.push(num); + } + } + } + } + return numbers; +} + +module.exports = { + checkAuth: (rules = []) => { + var authorised = false; + if (rules.length > 0) { + var now = new Date (); + var minuteOfDay = (now.getHours () * 60) + now.getMinutes (); // 0 - 1439 + var day = now.getDay (); // 1 - 7 + var date = now.getDate (); // 1 - 31 + var month = now.getMonth () + 1; // 1 - 12 + var actions = []; + rules.forEach ((rule) => { + var valid = false; + // Process rule + var r = { + startMinute: parseInt (rule.startTime.split (":")[0] * 60) + parseInt (rule.startTime.split (":")[1]), + endMinute: parseInt (rule.endTime.split (":")[0] * 60) + parseInt (rule.endTime.split (":")[1]), + days: resolveRange (rule.weekdays), + dates: resolveRange (rule.dates), + months: resolveRange (rule.months) + } + if ( + minuteOfDay >= r.startMinute && + minuteOfDay <= r.endMinute && + r.days.indexOf (day) !== -1 && + r.dates.indexOf (date) !== -1 && + r.months.indexOf (month) !== -1 + ) { + actions.push (rule.action.toLowerCase ()); + } + }); + if (actions.indexOf ("allow")) { + authorised = true; + } + if (actions.indexOf ("deny")) { + authorised = false; + } + } + return authorised; + } +} \ No newline at end of file