Merge 0.7->trunk
[prosody.git] / util / sasl / plain.lua
index 5c7ff68a770426ff01cead1c091963499ebcaf07..2abbc53a1688dd66c2d02253676a69446a5aac85 100644 (file)
@@ -1,5 +1,5 @@
 -- sasl.lua v0.4
--- Copyright (C) 2008-2009 Tobias Markmann
+-- Copyright (C) 2008-2010 Tobias Markmann
 --
 --    All rights reserved.
 --
@@ -17,25 +17,46 @@ local log = require "util.logger".init("sasl");
 
 module "plain"
 
---=========================
---SASL PLAIN according to RFC 4616
+-- ================================
+-- SASL PLAIN according to RFC 4616
+
+--[[
+Supported Authentication Backends
+
+plain:
+       function(username, realm)
+               return password, state;
+       end
+
+plain-test:
+       function(username, realm, password)
+               return true or false, state;
+       end
+       
+plain-hashed:
+       function(username, realm)
+               return hashed_password, hash_function, state;
+       end
+]]
+
 local function plain(self, message)
-       local response = message
-       local authorization = s_match(response, "([^%z]+)")
-       local authentication = s_match(response, "%z([^%z]+)%z")
-       local password = s_match(response, "%z[^%z]+%z([^%z]+)")
+       if not message then
+               return "failure", "malformed-request";
+       end
 
-       if authentication == nil or password == nil then
+       local authorization, authentication, password = s_match(message, "^([^%z]*)%z([^%z]+)%z([^%z]+)");
+
+       if not authorization then
                return "failure", "malformed-request";
        end
-       
+
        -- SASLprep password and authentication
        authentication = saslprep(authentication);
        password = saslprep(password);
-       
+
        if (not password) or (password == "") or (not authentication) or (authentication == "") then
                log("debug", "Username or password violates SASLprep.");
-               return "failure", "malformed-request";
+               return "failure", "malformed-request", "Invalid username or password.";
        end
 
        local correct, state = false, false;
@@ -45,6 +66,10 @@ local function plain(self, message)
                if correct_password == password then correct = true; else correct = false; end
        elseif self.profile.plain_test then
                correct, state = self.profile.plain_test(authentication, self.realm, password);
+       elseif self.profile.plain_hashed then
+               local hashed_password, hash_f;
+               hashed_password, hash_f, state = self.profile.plain_hashed(authentication, self.realm);
+               if hashed_password == hash_f(password) then correct = true; else correct = false; end
        end
 
        self.username = authentication
@@ -55,12 +80,12 @@ local function plain(self, message)
        if correct then
                return "success";
        else
-               return "failure", "not-authorized";
+               return "failure", "not-authorized", "Unable to authorize you with the authentication credentials you've sent.";
        end
 end
 
 function init(registerMechanism)
-       registerMechanism("PLAIN", {"plain", "plain_test"}, plain);
+       registerMechanism("PLAIN", {"plain", "plain_test", "plain_hashed"}, plain);
 end
 
-return _M;
\ No newline at end of file
+return _M;