Mercurial > prosody-modules
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 |
