From 5d9a6702c244eb4ab30ce96465d9deceedfe955a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 4 Mar 2010 12:58:25 +0100
Subject: Fix problem with SCRAM-SHA1 final message in <challenge/>.


diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
index 5e6179f..5dc924e 100644
--- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
+++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
@@ -36,7 +36,7 @@ ByteArray SCRAMSHA1ClientAuthenticator::getResponse() const {
 	if (step == Initial) {
 		return getGS2Header() + getInitialBareClientMessage();
 	}
-	else {
+	else if (step == Proof) {
 		ByteArray clientKey = HMACSHA1::getResult(saltedPassword, "Client Key");
 		ByteArray storedKey = SHA1::getHash(clientKey);
 		ByteArray clientSignature = HMACSHA1::getResult(storedKey, authMessage);
@@ -47,6 +47,9 @@ ByteArray SCRAMSHA1ClientAuthenticator::getResponse() const {
 		ByteArray result = ByteArray("c=") + Base64::encode(getGS2Header()) + ",r=" + clientnonce + serverNonce + ",p=" + Base64::encode(clientProof);
 		return result;
 	}
+	else {
+		return ByteArray();
+	}
 }
 
 bool SCRAMSHA1ClientAuthenticator::setChallenge(const ByteArray& challenge) {
@@ -90,10 +93,14 @@ bool SCRAMSHA1ClientAuthenticator::setChallenge(const ByteArray& challenge) {
 		step = Proof;
 		return true;
 	}
-	else {
+	else if (step == Proof) {
 		ByteArray result = ByteArray("v=") + ByteArray(Base64::encode(serverSignature));
+		step = Final;
 		return challenge == result;
 	}
+	else {
+		return true;
+	}
 }
 
 std::map<char, String> SCRAMSHA1ClientAuthenticator::parseMap(const String& s) {
diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h
index 6636139..3d28014 100644
--- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h
+++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h
@@ -23,7 +23,8 @@ namespace Swift {
 		private:
 			enum Step {
 				Initial,
-				Proof
+				Proof,
+        Final
 			} step;
 			String clientnonce;
 			ByteArray initialServerMessage;
diff --git a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp
index 5eedeb2..db69d13 100644
--- a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp
+++ b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp
@@ -22,6 +22,7 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST(testSetChallenge_MissingIterations);
 		CPPUNIT_TEST(testSetFinalChallenge);
 		CPPUNIT_TEST(testSetFinalChallenge_InvalidChallenge);
+		CPPUNIT_TEST(testGetResponseAfterFinalChallenge);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -155,6 +156,17 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture {
 
 			CPPUNIT_ASSERT(!result);
 		}
+
+		void testGetResponseAfterFinalChallenge() {
+			SCRAMSHA1ClientAuthenticator testling("abcdefgh");
+			testling.setCredentials("user", "pass", "");
+			testling.setChallenge(ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096"));
+			testling.setChallenge(ByteArray("v=Dd+Q20knZs9jeeK0pi1Mx1Se+yo="));
+
+			ByteArray result = testling.getResponse();
+
+			CPPUNIT_ASSERT_EQUAL(ByteArray(), result);
+		}
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(SCRAMSHA1ClientAuthenticatorTest);
-- 
cgit v0.10.2-6-g49f6