Merge 0.7->trunk
[prosody.git] / plugins / mod_auth_internal.lua
1 -- Prosody IM
2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
4 -- Copyright (C) 2010 Jeff Mitchell
5 --
6 -- This project is MIT/X11 licensed. Please see the
7 -- COPYING file in the source package for more information.
8 --
9
10 local datamanager = require "util.datamanager";
11 local log = require "util.logger".init("auth_internal");
12 local type = type;
13 local error = error;
14 local ipairs = ipairs;
15 local hashes = require "util.hashes";
16 local jid_bare = require "util.jid".bare;
17 local config = require "core.configmanager";
18 local usermanager = require "core.usermanager";
19 local new_sasl = require "util.sasl".new;
20 local nodeprep = require "util.encodings".stringprep.nodeprep;
21 local hosts = hosts;
22
23 local prosody = _G.prosody;
24
25 local is_cyrus = usermanager.is_cyrus;
26
27 function new_default_provider(host)
28         local provider = { name = "internal" };
29         log("debug", "initializing default authentication provider for host '%s'", host);
30
31         function provider.test_password(username, password)
32                 log("debug", "test password '%s' for user %s at host %s", password, username, module.host);
33                 if is_cyrus(host) then return nil, "Legacy auth not supported with Cyrus SASL."; end
34                 local credentials = datamanager.load(username, host, "accounts") or {};
35         
36                 if password == credentials.password then
37                         return true;
38                 else
39                         return nil, "Auth failed. Invalid username or password.";
40                 end
41         end
42
43         function provider.get_password(username)
44                 log("debug", "get_password for username '%s' at host '%s'", username, module.host);
45                 if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end
46                 return (datamanager.load(username, host, "accounts") or {}).password;
47         end
48         
49         function provider.set_password(username, password)
50                 if is_cyrus(host) then return nil, "Passwords unavailable for Cyrus SASL."; end
51                 local account = datamanager.load(username, host, "accounts");
52                 if account then
53                         account.password = password;
54                         return datamanager.store(username, host, "accounts", account);
55                 end
56                 return nil, "Account not available.";
57         end
58
59         function provider.user_exists(username)
60                 if is_cyrus(host) then return true; end
61                 local account = datamanager.load(username, host, "accounts");
62                 if not account then
63                         log("debug", "account not found for username '%s' at host '%s'", username, module.host);
64                         return nil, "Auth failed. Invalid username";
65                 end
66                 if account.password == nil or string.len(account.password) == 0 then
67                         log("debug", "account password not set or zero-length for username '%s' at host '%s'", username, module.host);
68                         return nil, "Auth failed. Password invalid.";
69                 end
70                 return true;
71         end
72
73         function provider.create_user(username, password)
74                 if is_cyrus(host) then return nil, "Account creation/modification not available with Cyrus SASL."; end
75                 return datamanager.store(username, host, "accounts", {password = password});
76         end
77
78         function provider.get_sasl_handler()
79                 local realm = module:get_option("sasl_realm") or module.host;
80                 local getpass_authentication_profile = {
81                         plain = function(username, realm)
82                                 local prepped_username = nodeprep(username);
83                                 if not prepped_username then
84                                         log("debug", "NODEprep failed on username: %s", username);
85                                         return "", nil;
86                                 end
87                                 local password = usermanager.get_password(prepped_username, realm);
88                                 if not password then
89                                         return "", nil;
90                                 end
91                                 return password, true;
92                         end
93                 };
94                 return new_sasl(realm, getpass_authentication_profile);
95         end
96         
97         return provider;
98 end
99
100 module:add_item("auth-provider", new_default_provider(module.host));
101