diff options
| -rw-r--r-- | Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp | 33 | ||||
| -rw-r--r-- | Swiften/SASL/SCRAMSHA1ClientAuthenticator.h | 3 | ||||
| -rw-r--r-- | Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp | 12 |
3 files changed, 32 insertions, 16 deletions
diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp index 8621b85..a261810 100644 --- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp +++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp @@ -9,12 +9,29 @@ #include "Swiften/StringCodecs/HMACSHA1.h" #include "Swiften/StringCodecs/PBKDF2.h" #include "Swiften/StringPrep/StringPrep.h" namespace Swift { +static String escape(const String& s) { + String result; + for (size_t i = 0; i < s.getUTF8Size(); ++i) { + if (s[i] == ',') { + result += "=2C"; + } + else if (s[i] == '=') { + result += "=3D"; + } + else { + result += s[i]; + } + } + return result; +} + + SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const String& nonce) : ClientAuthenticator("SCRAM-SHA-1"), step(Initial), clientnonce(nonce) { } ByteArray SCRAMSHA1ClientAuthenticator::getResponse() const { if (step == Initial) { return getGS2Header() + getInitialBareClientMessage(); @@ -106,26 +123,14 @@ std::map<char, String> SCRAMSHA1ClientAuthenticator::parseMap(const String& s) { } return result; } ByteArray SCRAMSHA1ClientAuthenticator::getInitialBareClientMessage() const { String authenticationID = StringPrep::getPrepared(getAuthenticationID(), StringPrep::SASLPrep); - String escapedAuthenticationID; - for (size_t i = 0; i < authenticationID.getUTF8Size(); ++i) { - if (authenticationID[i] == ',') { - escapedAuthenticationID += "=2C"; - } - else if (authenticationID[i] == '=') { - escapedAuthenticationID += "=3D"; - } - else { - escapedAuthenticationID += authenticationID[i]; - } - } - return ByteArray(String("n=" + escapedAuthenticationID + ",r=" + clientnonce)); + return ByteArray(String("n=" + escape(authenticationID) + ",r=" + clientnonce)); } ByteArray SCRAMSHA1ClientAuthenticator::getGS2Header() const { - return ByteArray("n,") + getAuthorizationID() + ","; + return ByteArray("n,") + (getAuthorizationID().isEmpty() ? "" : "a=" + escape(getAuthorizationID())) + ","; } } diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h index b8aaa17..6636139 100644 --- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h +++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.h @@ -13,15 +13,16 @@ namespace Swift { virtual ByteArray getResponse() const; virtual bool setChallenge(const ByteArray&); private: ByteArray getInitialBareClientMessage() const; - static std::map<char, String> parseMap(const String&); ByteArray getGS2Header() const; + static std::map<char, String> parseMap(const String&); + private: enum Step { Initial, Proof } step; String clientnonce; diff --git a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp index 6f64100..5eedeb2 100644 --- a/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp +++ b/Swiften/SASL/UnitTest/SCRAMSHA1ClientAuthenticatorTest.cpp @@ -8,12 +8,13 @@ using namespace Swift; class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(SCRAMSHA1ClientAuthenticatorTest); CPPUNIT_TEST(testGetInitialResponse); CPPUNIT_TEST(testGetInitialResponse_UsernameHasSpecialChars); CPPUNIT_TEST(testGetInitialResponse_WithAuthorizationID); + CPPUNIT_TEST(testGetInitialResponse_WithAuthorizationIDWithSpecialChars); CPPUNIT_TEST(testGetFinalResponse); CPPUNIT_TEST(testSetChallenge); CPPUNIT_TEST(testSetChallenge_InvalidClientNonce); CPPUNIT_TEST(testSetChallenge_OnlyClientNonce); CPPUNIT_TEST(testSetChallenge_InvalidIterations); CPPUNIT_TEST(testSetChallenge_ZeroIterations); @@ -48,13 +49,22 @@ class SCRAMSHA1ClientAuthenticatorTest : public CppUnit::TestFixture { void testGetInitialResponse_WithAuthorizationID() { SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH"); testling.setCredentials("user", "pass", "auth"); ByteArray response = testling.getResponse(); - CPPUNIT_ASSERT_EQUAL(String("n,auth,n=user,r=abcdefghABCDEFGH"), testling.getResponse().toString()); + CPPUNIT_ASSERT_EQUAL(String("n,a=auth,n=user,r=abcdefghABCDEFGH"), testling.getResponse().toString()); + } + + void testGetInitialResponse_WithAuthorizationIDWithSpecialChars() { + SCRAMSHA1ClientAuthenticator testling("abcdefghABCDEFGH"); + testling.setCredentials("user", "pass", "a=u,th"); + + ByteArray response = testling.getResponse(); + + CPPUNIT_ASSERT_EQUAL(String("n,a=a=3Du=2Cth,n=user,r=abcdefghABCDEFGH"), testling.getResponse().toString()); } void testGetFinalResponse() { SCRAMSHA1ClientAuthenticator testling("abcdefgh"); testling.setCredentials("user", "pass", ""); testling.setChallenge(ByteArray("r=abcdefghABCDEFGH,s=MTIzNDU2NzgK,i=4096")); |
Swift