Changeset

2184:0d1740f7b6e8 sasl

Store stage in SASL object.
author Tobias Markmann <tm@ayena.de>
date Fri, 28 Aug 2009 22:01:58 +0200
parents 2183:44e71e65da86
children 2185:e92339c48ee6
files util/sasl.lua
diffstat 1 files changed, 88 insertions(+), 91 deletions(-) [+]
line wrap: on
line diff
--- a/util/sasl.lua	Fri Aug 28 19:57:09 2009 +0200
+++ b/util/sasl.lua	Fri Aug 28 22:01:58 2009 +0200
@@ -151,7 +151,7 @@
 
 --=========================
 --SASL DIGEST-MD5 according to RFC 2831
-local function new_digest_md5(realm, credentials_handler)
+local function sasl_mechanism_digest_md5(self, message)
 	--TODO complete support for authzid
 
 	local function serialize(message)
@@ -225,112 +225,109 @@
 		return message;
 	end
 
-	local object = { mechanism = "DIGEST-MD5", realm = realm, credentials_handler = credentials_handler};
-
-	object.nonce = generate_uuid();
-	object.step = 0;
-	object.nonce_count = {};
+	if not self.nonce then
+		self.nonce = generate_uuid();
+		self.step = 0;
+		self.nonce_count = {};
+	end
 
-	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
+	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 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
+		-- 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 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
+		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 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
+		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.credentials_handler("DIGEST-MD5", response["username"], self.realm, response["realm"], 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 = "?";
-				end
+		--TODO maybe realm support
+		self.username = response["username"];
+		local password_encoding, Y = self.credentials_handler("DIGEST-MD5", response["username"], self.realm, response["realm"], 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 = Y..":"..response["nonce"]..":"..response["cnonce"];
+				A1 = "?";
 			end
-			local A2 = "AUTHENTICATE:"..protocol.."/"..domain;
-
-			local HA1 = md5(A1, true);
-			local HA2 = md5(A2, true);
+		else
+			A1 = Y..":"..response["nonce"]..":"..response["cnonce"];
+		end
+		local A2 = "AUTHENTICATE:"..protocol.."/"..domain;
 
-			local KD = HA1..":"..response["nonce"]..":"..response["nc"]..":"..response["cnonce"]..":"..response["qop"]..":"..HA2;
-			local response_value = md5(KD, true);
+		local HA1 = md5(A1, true);
+		local HA2 = md5(A2, true);
 
-			if response_value == response["response"] then
-				-- calculate rspauth
-				A2 = ":"..protocol.."/"..domain;
+		local KD = HA1..":"..response["nonce"]..":"..response["nc"]..":"..response["cnonce"]..":"..response["qop"]..":"..HA2;
+		local response_value = md5(KD, true);
+
+		if response_value == response["response"] then
+			-- calculate rspauth
+			A2 = ":"..protocol.."/"..domain;
 
-				HA1 = md5(A1, true);
-				HA2 = md5(A2, true);
+			HA1 = md5(A1, true);
+			HA2 = md5(A2, true);
 
-				KD = HA1..":"..response["nonce"]..":"..response["nc"]..":"..response["cnonce"]..":"..response["qop"]..":"..HA2
-				local rspauth = md5(KD, true);
-				self.authenticated = true;
-				return "challenge", serialize({rspauth = rspauth});
-			else
-				return "failure", "not-authorized", "The response provided by the client doesn't match the one we calculated."
-			end
-		elseif self.step == 3 then
-			if self.authenticated ~= nil then return "success"
-			else return "failure", "malformed-request" end
+			KD = HA1..":"..response["nonce"]..":"..response["nc"]..":"..response["cnonce"]..":"..response["qop"]..":"..HA2
+			local rspauth = md5(KD, true);
+			self.authenticated = true;
+			return "challenge", serialize({rspauth = rspauth});
+		else
+			return "failure", "not-authorized", "The response provided by the client doesn't match the one we calculated."
 		end
+	elseif self.step == 3 then
+		if self.authenticated ~= nil then return "success"
+		else return "failure", "malformed-request" end
 	end
-	return object;
 end
 
 return _M;