mod_admin_telnet: Don't rely on getpeerchain returning an empty list
[prosody.git] / util / sasl.lua
index 03219791e95261d8bbe5ef326a4ece0da11c3612..afb3861b08f90d70db33d9657da4df77efe43036 100644 (file)
@@ -35,7 +35,7 @@ local mechanisms = {};
 local backend_mechanism = {};
 
 -- register a new SASL mechanims
-local function registerMechanism(name, backends, f)
+function registerMechanism(name, backends, f)
        assert(type(name) == "string", "Parameter name MUST be a string.");
        assert(type(backends) == "string" or type(backends) == "table", "Parameter backends MUST be either a string or a table.");
        assert(type(f) == "function", "Parameter f MUST be a function.");
@@ -48,9 +48,19 @@ end
 
 -- create a new SASL object which can be used to authenticate clients
 function new(realm, profile)
-       local sasl_i = {profile = profile};
-       sasl_i.realm = realm;
-       return setmetatable(sasl_i, method);
+       local mechanisms = profile.mechanisms;
+       if not mechanisms then
+               mechanisms = {};
+               for backend, f in pairs(profile) do
+                       if backend_mechanism[backend] then
+                               for _, mechanism in ipairs(backend_mechanism[backend]) do
+                                       mechanisms[mechanism] = true;
+                               end
+                       end
+               end
+               profile.mechanisms = mechanisms;
+       end
+       return setmetatable({ profile = profile, realm = realm, mechs = mechanisms }, method);
 end
 
 -- get a fresh clone with the same realm and profile
@@ -60,43 +70,27 @@ end
 
 -- get a list of possible SASL mechanims to use
 function method:mechanisms()
-       local mechanisms = self.mechs;
-       if not mechanisms then
-               mechanisms = {}
-               for backend, f in pairs(self.profile) do
-                       if backend_mechanism[backend] then
-                               for _, mechanism in ipairs(backend_mechanism[backend]) do
-                                       mechanisms[mechanism] = true;
-                               end
-                       end
-               end
-               self.mechs = mechanisms;
-       end
-       return mechanisms;
+       return self.mechs;
 end
 
 -- select a mechanism to use
 function method:select(mechanism)
-       if self.mech_i then
-               return false;
+       if not self.selected and self.mechs[mechanism] then
+               self.selected = mechanism;
+               return true;
        end
-       
-       self.mech_i = mechanisms[self:mechanisms()[mechanism] and mechanism];
-       return (self.mech_i ~= nil);
 end
 
 -- feed new messages to process into the library
 function method:process(message)
        --if message == "" or message == nil then return "failure", "malformed-request" end
-       return self.mech_i(self, message);
+       return mechanisms[self.selected](self, message);
 end
 
 -- load the mechanisms
-local load_mechs = {"plain", "digest-md5", "anonymous", "scram"}
-for _, mech in ipairs(load_mechs) do
-       local name = "util.sasl."..mech;
-       local m = require(name);
-       m.init(registerMechanism)
-end
+require "util.sasl.plain"     .init(registerMechanism);
+require "util.sasl.digest-md5".init(registerMechanism);
+require "util.sasl.anonymous" .init(registerMechanism);
+require "util.sasl.scram"     .init(registerMechanism);
 
 return _M;