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