diff options
author | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2014-03-10 22:45:18 +0200 |
---|---|---|
committer | Kaarle Ritvanen <kaarle.ritvanen@datakunkku.fi> | 2014-03-24 01:18:13 +0200 |
commit | 7d9c43916b0600ac4879dfe9793eab807a83ab2b (patch) | |
tree | ec54ed64c9a557b6ea4ad88d31138a02d3e0cd04 /aconf/model/aaa.lua | |
parent | cb6c243dc356ef1d46d7ddb96e6ea6ae007c6cca (diff) | |
download | aconf-7d9c43916b0600ac4879dfe9793eab807a83ab2b.tar.bz2 aconf-7d9c43916b0600ac4879dfe9793eab807a83ab2b.tar.xz |
rename ACF2 to Alpine Configurator (aconf)
Diffstat (limited to 'aconf/model/aaa.lua')
-rw-r--r-- | aconf/model/aaa.lua | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/aconf/model/aaa.lua b/aconf/model/aaa.lua new file mode 100644 index 0000000..e324381 --- /dev/null +++ b/aconf/model/aaa.lua @@ -0,0 +1,88 @@ +--[[ +Copyright (c) 2012-2014 Kaarle Ritvanen +See LICENSE file for license details +--]] + +local M = require('aconf.model') +local object = require('aconf.object') + +local digest = require('crypto').digest + + +local Role = M.new() +Role.permissions = M.Set{type=M.Reference{scope='../../../permissions'}} + + +local function hash_password(algorithm, salt, password) + return algorithm..'$'..salt..'$'..digest(algorithm, salt..password) +end + +local hash_pattern = '^(%w+)%$(%w+)%$%x+$' + + +local Password = object.class(M.String) + +function Password:init() object.super(self, Password):init{detail=true} end + +function Password:normalize(context, value) + if value:find(hash_pattern) then return value end + + local salt = '' + for i = 1,12 do + local c = math.random(48, 109) + if c > 57 then c = c + 7 end + if c > 90 then c = c + 6 end + salt = salt..string.char(c) + end + return hash_password('sha256', salt, value) +end + + +local User = M.new() +User.password = Password +User.real_name = M.String +User.superuser = M.Boolean{default=false} +User.roles = M.Set{type=M.Reference{scope='../../../roles'}} + +function User:check_password(password) + if not self.password then return false end + local _, _, algorithm, salt = self.password:find(hash_pattern) + if not salt then return false end + return hash_password(algorithm, salt, password) == self.password +end + +function User:check_permission(permission) + -- TODO audit trail + print('check permission', permission) + + if self.superuser then return true end + + assert(getmetatable(self).txn:fetch('/auth/permissions')[permission]) + + for _, role in M.node.pairs(self.roles, true) do + for _, p in M.node.pairs(role.permissions, true) do + if p == permission then return true end + end + end + return false +end + + +local Authentication = M.new() +Authentication.users = M.Collection{type=User} +Authentication.roles = M.Collection{type=Role} +Authentication.permissions = M.Set{ + type=M.String, + addr='/volatile/aaa/permissions' +} + +M.register( + 'auth', + Authentication, + { + addr='/json'..require('posix').getcwd()..'/config/aaa.json', + ui_name='Authentication' + } +) + +M.permission.defaults('/auth') |