Mercurial > prosody-modules
comparison mod_auth_dovecot/mod_auth_dovecot.lua @ 269:74846ec9c29f
mod_auth_dovecot: Close socket on error
| author | Javier Torres <javitonino@gmail.com> |
|---|---|
| date | Sat, 30 Oct 2010 23:38:52 +0200 |
| parents | cfcd4efb0fa4 |
| children | 853ae6ae87bf |
comparison
equal
deleted
inserted
replaced
| 268:cfcd4efb0fa4 | 269:74846ec9c29f |
|---|---|
| 17 | 17 |
| 18 function new_default_provider(host) | 18 function new_default_provider(host) |
| 19 local provider = { name = "dovecot", c = nil }; | 19 local provider = { name = "dovecot", c = nil }; |
| 20 log("debug", "initializing dovecot authentication provider for host '%s'", host); | 20 log("debug", "initializing dovecot authentication provider for host '%s'", host); |
| 21 | 21 |
| 22 -- Closes the socket | |
| 23 function provider.close(self) | |
| 24 if (provider.c ~= nil) then | |
| 25 provider.c:close(); | |
| 26 end | |
| 27 provider.c = nil; | |
| 28 end | |
| 29 | |
| 22 -- The following connects to a new socket and send the handshake | 30 -- The following connects to a new socket and send the handshake |
| 23 function provider.connect(self) | 31 function provider.connect(self) |
| 24 -- Destroy old socket | 32 -- Destroy old socket |
| 25 if (provider.c ~= nil) then | 33 provider:close(); |
| 26 provider.c:close(); | |
| 27 end | |
| 28 | 34 |
| 29 provider.c = socket.unix(); | 35 provider.c = socket.unix(); |
| 30 | 36 |
| 31 -- Create a connection to dovecot socket | 37 -- Create a connection to dovecot socket |
| 32 local socket = "/var/run/dovecot/auth-login"; | 38 local socket = "/var/run/dovecot/auth-login"; |
| 33 local r, e = provider.c:connect(socket); | 39 local r, e = provider.c:connect(socket); |
| 34 if (not r) then | 40 if (not r) then |
| 35 log("warn", "error connecting to dovecot socket at '%s'. error was '%s'. check permissions", socket, e); | 41 log("warn", "error connecting to dovecot socket at '%s'. error was '%s'. check permissions", socket, e); |
| 42 provider:close(); | |
| 36 return false; | 43 return false; |
| 37 end | 44 end |
| 38 | 45 |
| 39 -- Send our handshake | 46 -- Send our handshake |
| 40 local pid = pposix.getpid(); | 47 local pid = pposix.getpid(); |
| 60 local v1 = parts(); | 67 local v1 = parts(); |
| 61 local v2 = parts(); | 68 local v2 = parts(); |
| 62 | 69 |
| 63 if (not (v1 == "1" and v2 == "1")) then | 70 if (not (v1 == "1" and v2 == "1")) then |
| 64 log("warn", "server version is not 1.1. it is %s.%s", v1, v2); | 71 log("warn", "server version is not 1.1. it is %s.%s", v1, v2); |
| 72 provider:close(); | |
| 65 return false; | 73 return false; |
| 66 end | 74 end |
| 67 elseif (first == "MECH") then | 75 elseif (first == "MECH") then |
| 68 -- Mechanisms should include PLAIN | 76 -- Mechanisms should include PLAIN |
| 69 local ok = false; | 77 local ok = false; |
| 72 ok = true; | 80 ok = true; |
| 73 end | 81 end |
| 74 end | 82 end |
| 75 if (not ok) then | 83 if (not ok) then |
| 76 log("warn", "server doesn't support PLAIN mechanism. It supports '%s'", l); | 84 log("warn", "server doesn't support PLAIN mechanism. It supports '%s'", l); |
| 85 provider:close(); | |
| 77 return false; | 86 return false; |
| 78 end | 87 end |
| 79 elseif (first == "DONE") then | 88 elseif (first == "DONE") then |
| 80 done = true; | 89 done = true; |
| 81 end | 90 end |
| 82 end | 91 end |
| 83 return true; | 92 return true; |
| 84 end | 93 end |
| 85 | 94 |
| 95 -- Wrapper for send(). Handles errors | |
| 86 function provider.send(self, data) | 96 function provider.send(self, data) |
| 87 local r, e = provider.c:send(data); | 97 local r, e = provider.c:send(data); |
| 88 if (not r) then | 98 if (not r) then |
| 89 log("warn", "error sending '%s' to dovecot. error was '%s'", data, e); | 99 log("warn", "error sending '%s' to dovecot. error was '%s'", data, e); |
| 100 provider:close(); | |
| 90 return false; | 101 return false; |
| 91 end | 102 end |
| 92 return true; | 103 return true; |
| 93 end | 104 end |
| 94 | 105 |
| 106 -- Wrapper for receive(). Handles errors | |
| 95 function provider.receive(self) | 107 function provider.receive(self) |
| 96 local r, e = provider.c:receive(); | 108 local r, e = provider.c:receive(); |
| 97 if (not r) then | 109 if (not r) then |
| 98 log("warn", "error receiving data from dovecot. error was '%s'", socket, e); | 110 log("warn", "error receiving data from dovecot. error was '%s'", socket, e); |
| 111 provider:close(); | |
| 99 return false; | 112 return false; |
| 100 end | 113 end |
| 101 return r; | 114 return r; |
| 102 end | 115 end |
| 103 | 116 |
| 104 function provider.test_password(username, password) | 117 function provider.test_password(username, password) |
| 105 log("debug", "test password '%s' for user %s at host %s", password, username, module.host); | 118 log("debug", "test password '%s' for user %s at host %s", password, username, module.host); |
| 106 | 119 |
| 107 if (not provider:connect()) then | 120 local tries = 0; |
| 108 return nil, "Auth failed. Dovecot communications error"; | 121 |
| 122 if (provider.c == nil or tries > 0) then | |
| 123 if (not provider:connect()) then | |
| 124 return nil, "Auth failed. Dovecot communications error"; | |
| 125 end | |
| 109 end | 126 end |
| 110 | 127 |
| 111 -- Send auth data | 128 -- Send auth data |
| 112 username = username .. "@" .. module.host; -- FIXME: this is actually a hack for my server | 129 username = username .. "@" .. module.host; -- FIXME: this is actually a hack for my server |
| 113 local b64 = base64.encode(username .. "\0" .. username .. "\0" .. password); | 130 local b64 = base64.encode(username .. "\0" .. username .. "\0" .. password); |
| 128 return true; | 145 return true; |
| 129 else | 146 else |
| 130 return nil, "Auth failed. Invalid username or password."; | 147 return nil, "Auth failed. Invalid username or password."; |
| 131 end | 148 end |
| 132 end | 149 end |
| 133 | 150 |
| 134 function provider.get_password(username) | 151 function provider.get_password(username) |
| 135 return nil, "Cannot get_password in dovecot backend."; | 152 return nil, "Cannot get_password in dovecot backend."; |
| 136 end | 153 end |
| 137 | 154 |
| 138 function provider.set_password(username, password) | 155 function provider.set_password(username, password) |
| 139 return nil, "Cannot set_password in dovecot backend."; | 156 return nil, "Cannot set_password in dovecot backend."; |
| 140 end | 157 end |
| 141 | 158 |
| 142 function provider.user_exists(username) | 159 function provider.user_exists(username) |
| 143 --TODO: Send an auth request. If it returns FAIL <id> user=<user> then user exists. | 160 --TODO: Send an auth request. If it returns FAIL <id> user=<user> then user exists. |
| 144 return nil, "user_exists not yet implemented in dovecot backend."; | 161 return nil, "user_exists not yet implemented in dovecot backend."; |
| 145 end | 162 end |
| 146 | 163 |
| 147 function provider.create_user(username, password) | 164 function provider.create_user(username, password) |
| 148 return nil, "Cannot create_user in dovecot backend."; | 165 return nil, "Cannot create_user in dovecot backend."; |
| 149 end | 166 end |
| 150 | 167 |
| 151 function provider.get_sasl_handler() | 168 function provider.get_sasl_handler() |
| 152 local realm = module:get_option("sasl_realm") or module.host; | 169 local realm = module:get_option("sasl_realm") or module.host; |
| 153 local getpass_authentication_profile = { | 170 local getpass_authentication_profile = { |
| 154 plain_test = function(username, password, realm) | 171 plain_test = function(username, password, realm) |
| 155 local prepped_username = nodeprep(username); | 172 local prepped_username = nodeprep(username); |
| 157 log("debug", "NODEprep failed on username: %s", username); | 174 log("debug", "NODEprep failed on username: %s", username); |
| 158 return "", nil; | 175 return "", nil; |
| 159 end | 176 end |
| 160 return usermanager.test_password(prepped_username, realm, password), true; | 177 return usermanager.test_password(prepped_username, realm, password), true; |
| 161 end | 178 end |
| 162 }; | 179 }; |
| 163 return new_sasl(realm, getpass_authentication_profile); | 180 return new_sasl(realm, getpass_authentication_profile); |
| 164 end | 181 end |
| 165 | 182 |
| 166 return provider; | 183 return provider; |
| 167 end | 184 end |
| 168 | 185 |
| 169 module:add_item("auth-provider", new_default_provider(module.host)); | 186 module:add_item("auth-provider", new_default_provider(module.host)); |
| 170 |
