diff 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
line wrap: on
line diff
--- a/mod_auth_dovecot/mod_auth_dovecot.lua	Sat Oct 30 23:38:39 2010 +0200
+++ b/mod_auth_dovecot/mod_auth_dovecot.lua	Sat Oct 30 23:38:52 2010 +0200
@@ -19,12 +19,18 @@
 	local provider = { name = "dovecot", c = nil };
 	log("debug", "initializing dovecot authentication provider for host '%s'", host);
 	
+	-- Closes the socket
+	function provider.close(self)
+		if (provider.c ~= nil) then
+			provider.c:close();
+		end
+		provider.c = nil;
+	end
+	
 	-- The following connects to a new socket and send the handshake
 	function provider.connect(self)
 		-- Destroy old socket
-		if (provider.c ~= nil) then
-			provider.c:close();
-		end
+		provider:close();
 		
 		provider.c = socket.unix();
 		
@@ -33,6 +39,7 @@
 		local r, e = provider.c:connect(socket);
 		if (not r) then
 			log("warn", "error connecting to dovecot socket at '%s'. error was '%s'. check permissions", socket, e);
+			provider:close();
 			return false;
 		end
 		
@@ -62,6 +69,7 @@
 				
 				if (not (v1 == "1" and v2 == "1")) then
 					log("warn", "server version is not 1.1. it is %s.%s", v1, v2);
+					provider:close();
 					return false;
 				end
 			elseif (first == "MECH") then
@@ -74,6 +82,7 @@
 				end
 				if (not ok) then
 					log("warn", "server doesn't support PLAIN mechanism. It supports '%s'", l);
+					provider:close();
 					return false;
 				end
 			elseif (first == "DONE") then
@@ -83,19 +92,23 @@
 		return true;
 	end
 	
+	-- Wrapper for send(). Handles errors
 	function provider.send(self, data)
 		local r, e = provider.c:send(data);
 		if (not r) then
 			log("warn", "error sending '%s' to dovecot. error was '%s'", data, e);
+			provider:close();
 			return false;
 		end
 		return true;
 	end
 	
+	-- Wrapper for receive(). Handles errors
 	function provider.receive(self)
 		local r, e = provider.c:receive();
 		if (not r) then
 			log("warn", "error receiving data from dovecot. error was '%s'", socket, e);
+			provider:close();
 			return false;
 		end
 		return r;
@@ -104,8 +117,12 @@
 	function provider.test_password(username, password)
 		log("debug", "test password '%s' for user %s at host %s", password, username, module.host);
 		
-		if (not provider:connect()) then
-			return nil, "Auth failed. Dovecot communications error";
+		local tries = 0;
+		
+		if (provider.c == nil or tries > 0) then
+			if (not provider:connect()) then
+				return nil, "Auth failed. Dovecot communications error";
+			end
 		end
 		
 		-- Send auth data
@@ -130,7 +147,7 @@
 			return nil, "Auth failed. Invalid username or password.";
 		end
 	end
-	
+
 	function provider.get_password(username)
 		return nil, "Cannot get_password in dovecot backend.";
 	end
@@ -138,16 +155,16 @@
 	function provider.set_password(username, password)
 		return nil, "Cannot set_password in dovecot backend.";
 	end
-	
+
 	function provider.user_exists(username)
 		--TODO: Send an auth request. If it returns FAIL <id> user=<user> then user exists.
-				return nil, "user_exists not yet implemented in dovecot backend.";
+		return nil, "user_exists not yet implemented in dovecot backend.";
 	end
-	
+
 	function provider.create_user(username, password)
 		return nil, "Cannot create_user in dovecot backend.";
 	end
-	
+
 	function provider.get_sasl_handler()
 		local realm = module:get_option("sasl_realm") or module.host;
 		local getpass_authentication_profile = {
@@ -159,12 +176,11 @@
 			end
 			return usermanager.test_password(prepped_username, realm, password), true;
 		end
-	};
-	return new_sasl(realm, getpass_authentication_profile);
-end
-
-return provider;
+		};
+		return new_sasl(realm, getpass_authentication_profile);
+	end
+	
+	return provider;
 end
 
 module:add_item("auth-provider", new_default_provider(module.host));
-