- local object = { mechanism = "DIGEST-MD5", realm = realm, password_handler = password_handler};
-
- object.nonce = generate_uuid();
- object.step = 0;
- object.nonce_count = {};
-
- function object.feed(self, message)
- self.step = self.step + 1;
- if (self.step == 1) then
- local challenge = serialize({ nonce = object.nonce,
- qop = "auth",
- charset = "utf-8",
- algorithm = "md5-sess",
- realm = self.realm});
- return "challenge", challenge;
- elseif (self.step == 2) then
- local response = parse(message);
- -- check for replay attack
- if response["nc"] then
- if self.nonce_count[response["nc"]] then return "failure", "not-authorized" end
- end
-
- -- check for username, it's REQUIRED by RFC 2831
- if not response["username"] then
- return "failure", "malformed-request";
- end
- self["username"] = response["username"];
-
- -- check for nonce, ...
- if not response["nonce"] then
- return "failure", "malformed-request";
- else
- -- check if it's the right nonce
- if response["nonce"] ~= tostring(self.nonce) then return "failure", "malformed-request" end
- end
-
- if not response["cnonce"] then return "failure", "malformed-request", "Missing entry for cnonce in SASL message." end
- if not response["qop"] then response["qop"] = "auth" end
-
- if response["realm"] == nil or response["realm"] == "" then
- response["realm"] = "";
- elseif response["realm"] ~= self.realm then
- return "failure", "not-authorized", "Incorrect realm value";
- end
-
- local decoder;
- if response["charset"] == nil then
- decoder = utf8tolatin1ifpossible;
- elseif response["charset"] ~= "utf-8" then
- return "failure", "incorrect-encoding", "The client's response uses "..response["charset"].." for encoding with isn't supported by sasl.lua. Supported encodings are latin or utf-8.";
- end
-
- local domain = "";
- local protocol = "";
- if response["digest-uri"] then
- protocol, domain = response["digest-uri"]:match("(%w+)/(.*)$");
- if protocol == nil or domain == nil then return "failure", "malformed-request" end
- else
- return "failure", "malformed-request", "Missing entry for digest-uri in SASL message."
- end
-
- --TODO maybe realm support
- self.username = response["username"];
- local password_encoding, Y = self.password_handler(response["username"], domain, response["realm"], "DIGEST-MD5", decoder);
- if Y == nil then return "failure", "not-authorized"
- elseif Y == false then return "failure", "account-disabled" end
- local A1 = "";
- if response.authzid then
- if response.authzid == self.username.."@"..self.realm then
- -- COMPAT
- log("warn", "Client is violating XMPP RFC. See section 6.1 of RFC 3920.");
- A1 = Y..":"..response["nonce"]..":"..response["cnonce"]..":"..response.authzid;
- else
- A1 = "?";
+-- get a fresh clone with the same realm and profile
+function method:clean_clone()
+ return new(self.realm, self.profile)
+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;