comparison mod_auth_dovecot/mod_auth_dovecot.lua @ 261:0f46fb2dbc79

mod_auth_dovecot: Initial commit of Dovecot authentication backend by Javier Torres
author Matthew Wild <mwild1@gmail.com>
date Sun, 10 Oct 2010 21:43:50 +0100
parents
children 76f3310ec113
comparison
equal deleted inserted replaced
260:1fdd201c1d43 261:0f46fb2dbc79
1 -- Dovecot authentication backend for Prosody
2 --
3 -- Copyright (C) 2010 Javier Torres
4 -- Copyright (C) 2008-2010 Matthew Wild
5 -- Copyright (C) 2008-2010 Waqas Hussain
6 --
7
8 local socket_unix = require "socket.unix";
9 local datamanager = require "util.datamanager";
10 local log = require "util.logger".init("auth_internal_plain");
11 local new_sasl = require "util.sasl".new;
12 local nodeprep = require "util.encodings".stringprep.nodeprep;
13 local base64 = require "util.encodings".base64;
14
15 local prosody = _G.prosody;
16
17 function new_default_provider(host)
18 local provider = { name = "dovecot" };
19 log("debug", "initializing dovecot authentication provider for host '%s'", host);
20
21 function provider.test_password(username, password)
22 log("debug", "test password '%s' for user %s at host %s", password, username, module.host);
23
24 c = assert(socket.unix());
25 assert(c:connect("/var/run/dovecot/auth-login")); -- FIXME: Hardcoded is bad
26
27 local pid = "12345"; -- FIXME: this should be an unique number between processes, recommendation is PID
28
29 -- Send our handshake
30 -- FIXME: Oh no! There are asserts everywhere
31 assert(c:send("VERSION\t1\t1\n"));
32 assert(c:send("CPID\t" .. pid .. "\n"));
33
34 -- Check their handshake
35 local done = false;
36 while (not done) do
37 local l = assert(c:receive());
38 parts = string.gmatch(l, "[^\t]+");
39 first = parts();
40 if (first == "VERSION") then
41 assert(parts() == "1");
42 assert(parts() == "1");
43 elseif (first == "MECH") then
44 local ok = false;
45 for p in parts do
46 if p == "PLAIN" then
47 ok = true;
48 end
49 end
50 assert(ok);
51 elseif (first == "DONE") then
52 done = true;
53 end
54 end
55
56 -- Send auth data
57 username = username .. "@" .. module.host; -- FIXME: this is actually a hack for my server
58 local b64 = base64.encode(username .. "\0" .. username .. "\0" .. password);
59 local id = "54321"; -- FIXME: probably can just be a fixed value if making one request per connection
60 assert(c:send("AUTH\t" .. id .. "\tPLAIN\tservice=XMPP\tresp=" .. b64 .. "\n"));
61 local l = assert(c:receive());
62 assert(c:close());
63 local parts = string.gmatch(l, "[^\t]+");
64
65 if (parts() == "OK") then
66 return true;
67 else
68 return nil, "Auth failed. Invalid username or password.";
69 end
70 end
71
72 function provider.get_password(username)
73 return nil, "Cannot get_password in dovecot backend.";
74 end
75
76 function provider.set_password(username, password)
77 return nil, "Cannot set_password in dovecot backend.";
78 end
79
80 function provider.user_exists(username)
81 --TODO: Send an auth request. If it returns FAIL <id> user=<user> then user exists.
82 return nil, "user_exists not yet implemented in dovecot backend.";
83 end
84
85 function provider.create_user(username, password)
86 return nil, "Cannot create_user in dovecot backend.";
87 end
88
89 function provider.get_sasl_handler()
90 local realm = module:get_option("sasl_realm") or module.host;
91 local getpass_authentication_profile = {
92 plain_test = function(username, password, realm)
93 local prepped_username = nodeprep(username);
94 if not prepped_username then
95 log("debug", "NODEprep failed on username: %s", username);
96 return "", nil;
97 end
98 return usermanager.test_password(prepped_username, realm, password), true;
99 end
100 };
101 return new_sasl(realm, getpass_authentication_profile);
102 end
103
104 return provider;
105 end
106
107 module:add_item("auth-provider", new_default_provider(module.host));
108