Software /
code /
prosody
Comparison
core/usermanager.lua @ 2987:0acfae4da199
usermanager: Support for pluggable authentication providers
author | Matthew Wild <mwild1@gmail.com> |
---|---|
date | Wed, 05 May 2010 01:05:58 +0100 |
parent | 2934:060bb8217fea |
child | 2999:9a8f942433c4 |
comparison
equal
deleted
inserted
replaced
2986:fff153f7f4de | 2987:0acfae4da199 |
---|---|
14 local hashes = require "util.hashes"; | 14 local hashes = require "util.hashes"; |
15 local jid_bare = require "util.jid".bare; | 15 local jid_bare = require "util.jid".bare; |
16 local config = require "core.configmanager"; | 16 local config = require "core.configmanager"; |
17 local hosts = hosts; | 17 local hosts = hosts; |
18 | 18 |
19 local prosody = _G.prosody; | |
20 | |
19 module "usermanager" | 21 module "usermanager" |
22 | |
23 local new_default_provider; | |
24 | |
25 prosody.events.add_handler("host-activated", function (host) | |
26 local host_session = hosts[host]; | |
27 host_session.events.add_handler("item-added/auth-provider", function (provider) | |
28 if config.get(host, "core", "authentication") == provider.name then | |
29 host_session.users = provider; | |
30 end | |
31 end); | |
32 host_session.events.add_handler("item-removed/auth-provider", function (provider) | |
33 if host_session.users == provider then | |
34 host_session.users = new_default_provider(host); | |
35 end | |
36 end); | |
37 host_session.users = new_default_provider(host); -- Start with the default usermanager provider | |
38 end); | |
20 | 39 |
21 local function is_cyrus(host) return config.get(host, "core", "sasl_backend") == "cyrus"; end | 40 local function is_cyrus(host) return config.get(host, "core", "sasl_backend") == "cyrus"; end |
22 | 41 |
23 function validate_credentials(host, username, password, method) | 42 function new_default_provider(host) |
24 log("debug", "User '%s' is being validated", username); | 43 local provider = {}; |
25 if is_cyrus(host) then return nil, "Legacy auth not supported with Cyrus SASL."; end | 44 |
26 local credentials = datamanager.load(username, host, "accounts") or {}; | 45 function provider.test_password(username, password) |
27 | 46 if is_cyrus(host) then return nil, "Legacy auth not supported with Cyrus SASL."; end |
28 if method == nil then method = "PLAIN"; end | 47 local credentials = datamanager.load(username, host, "accounts") or {}; |
29 if method == "PLAIN" and credentials.password then -- PLAIN, do directly | 48 |
30 if password == credentials.password then | 49 if password == credentials.password then |
31 return true; | 50 return true; |
32 else | 51 else |
33 return nil, "Auth failed. Invalid username or password."; | 52 return nil, "Auth failed. Invalid username or password."; |
34 end | 53 end |
35 end | |
36 -- must do md5 | |
37 -- make credentials md5 | |
38 local pwd = credentials.password; | |
39 if not pwd then pwd = credentials.md5; else pwd = hashes.md5(pwd, true); end | |
40 -- make password md5 | |
41 if method == "PLAIN" then | |
42 password = hashes.md5(password or "", true); | |
43 elseif method ~= "DIGEST-MD5" then | |
44 return nil, "Unsupported auth method"; | |
45 end | 54 end |
46 -- compare | 55 |
47 if password == pwd then | 56 function provider.get_password(username) |
48 return true; | 57 if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end |
49 else | 58 return (datamanager.load(username, host, "accounts") or {}).password; |
50 return nil, "Auth failed. Invalid username or password."; | |
51 end | 59 end |
60 | |
61 function provider.set_password(username, password) | |
62 if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end | |
63 local account = datamanager.load(username, host, "accounts"); | |
64 if account then | |
65 account.password = password; | |
66 return datamanager.store(username, host, "accounts", account); | |
67 end | |
68 return nil, "Account not available."; | |
69 end | |
70 | |
71 function provider.user_exists(username) | |
72 if is_cyrus(host) then return true; end | |
73 return datamanager.load(username, host, "accounts") ~= nil; -- FIXME also check for empty credentials | |
74 end | |
75 | |
76 function provider.create_user(username, password) | |
77 if is_cyrus(host) then return nil, "Account creation/modification not available with Cyrus SASL."; end | |
78 return datamanager.store(username, host, "accounts", {password = password}); | |
79 end | |
80 | |
81 function provider.get_supported_methods() | |
82 return {["PLAIN"] = true, ["DIGEST-MD5"] = true}; -- TODO this should be taken from the config | |
83 end | |
84 | |
85 function provider.is_admin(jid) | |
86 host = host or "*"; | |
87 local admins = config.get(host, "core", "admins"); | |
88 if host ~= "*" and admins == config.get("*", "core", "admins") then | |
89 return nil; | |
90 end | |
91 if type(admins) == "table" then | |
92 jid = jid_bare(jid); | |
93 for _,admin in ipairs(admins) do | |
94 if admin == jid then return true; end | |
95 end | |
96 elseif admins then | |
97 log("warn", "Option 'admins' for host '%s' is not a table", host); | |
98 end | |
99 return nil; | |
100 end | |
101 return provider; | |
102 end | |
103 | |
104 function validate_credentials(host, username, password, method) | |
105 return hosts[host].users.test_password(username, password); | |
52 end | 106 end |
53 | 107 |
54 function get_password(username, host) | 108 function get_password(username, host) |
55 if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end | 109 return hosts[host].users.get_password(username); |
56 return (datamanager.load(username, host, "accounts") or {}).password | |
57 end | 110 end |
111 | |
58 function set_password(username, host, password) | 112 function set_password(username, host, password) |
59 if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end | 113 return hosts[host].users.set_password(username, password); |
60 local account = datamanager.load(username, host, "accounts"); | |
61 if account then | |
62 account.password = password; | |
63 return datamanager.store(username, host, "accounts", account); | |
64 end | |
65 return nil, "Account not available."; | |
66 end | 114 end |
67 | 115 |
68 function user_exists(username, host) | 116 function user_exists(username, host) |
69 if is_cyrus(host) then return true; end | 117 return hosts[host].users.user_exists(username); |
70 return datamanager.load(username, host, "accounts") ~= nil; -- FIXME also check for empty credentials | |
71 end | 118 end |
72 | 119 |
73 function create_user(username, password, host) | 120 function create_user(username, password, host) |
74 if is_cyrus(host) then return nil, "Account creation/modification not available with Cyrus SASL."; end | 121 return hosts[host].users.create_user(username, password); |
75 return datamanager.store(username, host, "accounts", {password = password}); | |
76 end | 122 end |
77 | 123 |
78 function get_supported_methods(host) | 124 function get_supported_methods(host) |
79 return {["PLAIN"] = true, ["DIGEST-MD5"] = true}; -- TODO this should be taken from the config | 125 return hosts[host].users.get_supported_methods(); |
80 end | 126 end |
81 | 127 |
82 function is_admin(jid, host) | 128 function is_admin(jid, host) |
83 host = host or "*"; | 129 return hosts[host].users.is_admin(jid); |
84 local admins = config.get(host, "core", "admins"); | |
85 if host ~= "*" and admins == config.get("*", "core", "admins") then | |
86 return nil; | |
87 end | |
88 if type(admins) == "table" then | |
89 jid = jid_bare(jid); | |
90 for _,admin in ipairs(admins) do | |
91 if admin == jid then return true; end | |
92 end | |
93 elseif admins then log("warn", "Option 'admins' for host '%s' is not a table", host); end | |
94 return nil; | |
95 end | 130 end |
96 | 131 |
97 return _M; | 132 return _M; |