diff options
Diffstat (limited to 'Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp')
-rw-r--r-- | Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp | 273 |
1 files changed, 137 insertions, 136 deletions
diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp index 554e9f0..3c00402 100644 --- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp +++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -8,30 +8,31 @@ #include <cassert> #include <map> + #include <boost/lexical_cast.hpp> +#include <Swiften/Base/Concat.h> #include <Swiften/Crypto/CryptoProvider.h> +#include <Swiften/IDN/IDNConverter.h> #include <Swiften/StringCodecs/Base64.h> #include <Swiften/StringCodecs/PBKDF2.h> -#include <Swiften/IDN/IDNConverter.h> -#include <Swiften/Base/Concat.h> namespace Swift { static std::string escape(const std::string& s) { - std::string result; - for (size_t i = 0; i < s.size(); ++i) { - if (s[i] == ',') { - result += "=2C"; - } - else if (s[i] == '=') { - result += "=3D"; - } - else { - result += s[i]; - } - } - return result; + std::string result; + for (char i : s) { + if (i == ',') { + result += "=2C"; + } + else if (i == '=') { + result += "=3D"; + } + else { + result += i; + } + } + return result; } @@ -39,144 +40,144 @@ SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const std::string& no } boost::optional<SafeByteArray> SCRAMSHA1ClientAuthenticator::getResponse() const { - if (step == Initial) { - return createSafeByteArray(concat(getGS2Header(), getInitialBareClientMessage())); - } - else if (step == Proof) { - ByteArray clientKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Client Key")); - ByteArray storedKey = crypto->getSHA1Hash(clientKey); - ByteArray clientSignature = crypto->getHMACSHA1(createSafeByteArray(storedKey), authMessage); - ByteArray clientProof = clientKey; - for (unsigned int i = 0; i < clientProof.size(); ++i) { - clientProof[i] ^= clientSignature[i]; - } - ByteArray result = concat(getFinalMessageWithoutProof(), createByteArray(",p="), createByteArray(Base64::encode(clientProof))); - return createSafeByteArray(result); - } - else { - return boost::optional<SafeByteArray>(); - } + if (step == Initial) { + return createSafeByteArray(concat(getGS2Header(), getInitialBareClientMessage())); + } + else if (step == Proof) { + ByteArray clientKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Client Key")); + ByteArray storedKey = crypto->getSHA1Hash(clientKey); + ByteArray clientSignature = crypto->getHMACSHA1(createSafeByteArray(storedKey), authMessage); + ByteArray clientProof = clientKey; + for (unsigned int i = 0; i < clientProof.size(); ++i) { + clientProof[i] ^= clientSignature[i]; + } + ByteArray result = concat(getFinalMessageWithoutProof(), createByteArray(",p="), createByteArray(Base64::encode(clientProof))); + return createSafeByteArray(result); + } + else { + return boost::optional<SafeByteArray>(); + } } bool SCRAMSHA1ClientAuthenticator::setChallenge(const boost::optional<ByteArray>& challenge) { - if (step == Initial) { - if (!challenge) { - return false; - } - initialServerMessage = *challenge; - - std::map<char, std::string> keys = parseMap(byteArrayToString(initialServerMessage)); - - // Extract the salt - ByteArray salt = Base64::decode(keys['s']); - - // Extract the server nonce - std::string clientServerNonce = keys['r']; - if (clientServerNonce.size() <= clientnonce.size()) { - return false; - } - std::string receivedClientNonce = clientServerNonce.substr(0, clientnonce.size()); - if (receivedClientNonce != clientnonce) { - return false; - } - serverNonce = createByteArray(clientServerNonce.substr(clientnonce.size(), clientServerNonce.npos)); - - // Extract the number of iterations - int iterations = 0; - try { - iterations = boost::lexical_cast<int>(keys['i']); - } - catch (const boost::bad_lexical_cast&) { - return false; - } - if (iterations <= 0) { - return false; - } - - // Compute all the values needed for the server signature - try { - saltedPassword = PBKDF2::encode(idnConverter->getStringPrepared(getPassword(), IDNConverter::SASLPrep), salt, iterations, crypto); - } - catch (const std::exception&) { - } - authMessage = concat(getInitialBareClientMessage(), createByteArray(","), initialServerMessage, createByteArray(","), getFinalMessageWithoutProof()); - ByteArray serverKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Server Key")); - serverSignature = crypto->getHMACSHA1(serverKey, authMessage); - - step = Proof; - return true; - } - else if (step == Proof) { - ByteArray result = concat(createByteArray("v="), createByteArray(Base64::encode(serverSignature))); - step = Final; - return challenge && challenge == result; - } - else { - return true; - } + if (step == Initial) { + if (!challenge) { + return false; + } + initialServerMessage = *challenge; + + std::map<char, std::string> keys = parseMap(byteArrayToString(initialServerMessage)); + + // Extract the salt + ByteArray salt = Base64::decode(keys['s']); + + // Extract the server nonce + std::string clientServerNonce = keys['r']; + if (clientServerNonce.size() <= clientnonce.size()) { + return false; + } + std::string receivedClientNonce = clientServerNonce.substr(0, clientnonce.size()); + if (receivedClientNonce != clientnonce) { + return false; + } + serverNonce = createByteArray(clientServerNonce.substr(clientnonce.size(), clientServerNonce.npos)); + + // Extract the number of iterations + int iterations = 0; + try { + iterations = boost::lexical_cast<int>(keys['i']); + } + catch (const boost::bad_lexical_cast&) { + return false; + } + if (iterations <= 0) { + return false; + } + + // Compute all the values needed for the server signature + try { + saltedPassword = PBKDF2::encode(idnConverter->getStringPrepared(getPassword(), IDNConverter::SASLPrep), salt, iterations, crypto); + } + catch (const std::exception&) { + } + authMessage = concat(getInitialBareClientMessage(), createByteArray(","), initialServerMessage, createByteArray(","), getFinalMessageWithoutProof()); + ByteArray serverKey = crypto->getHMACSHA1(saltedPassword, createByteArray("Server Key")); + serverSignature = crypto->getHMACSHA1(serverKey, authMessage); + + step = Proof; + return true; + } + else if (step == Proof) { + ByteArray result = concat(createByteArray("v="), createByteArray(Base64::encode(serverSignature))); + step = Final; + return challenge && challenge == result; + } + else { + return true; + } } std::map<char, std::string> SCRAMSHA1ClientAuthenticator::parseMap(const std::string& s) { - std::map<char, std::string> result; - if (s.size() > 0) { - char key = 0; - std::string value; - size_t i = 0; - bool expectKey = true; - while (i < s.size()) { - if (expectKey) { - key = s[i]; - expectKey = false; - i++; - } - else if (s[i] == ',') { - result[key] = value; - value = ""; - expectKey = true; - } - else { - value += s[i]; - } - i++; - } - result[key] = value; - } - return result; + std::map<char, std::string> result; + if (s.size() > 0) { + char key = 0; + std::string value; + size_t i = 0; + bool expectKey = true; + while (i < s.size()) { + if (expectKey) { + key = s[i]; + expectKey = false; + i++; + } + else if (s[i] == ',') { + result[key] = value; + value = ""; + expectKey = true; + } + else { + value += s[i]; + } + i++; + } + result[key] = value; + } + return result; } ByteArray SCRAMSHA1ClientAuthenticator::getInitialBareClientMessage() const { - std::string authenticationID; - try { - authenticationID = idnConverter->getStringPrepared(getAuthenticationID(), IDNConverter::SASLPrep); - } - catch (const std::exception&) { - } - return createByteArray(std::string("n=" + escape(authenticationID) + ",r=" + clientnonce)); + std::string authenticationID; + try { + authenticationID = idnConverter->getStringPrepared(getAuthenticationID(), IDNConverter::SASLPrep); + } + catch (const std::exception&) { + } + return createByteArray(std::string("n=" + escape(authenticationID) + ",r=" + clientnonce)); } ByteArray SCRAMSHA1ClientAuthenticator::getGS2Header() const { - ByteArray channelBindingHeader(createByteArray("n")); - if (tlsChannelBindingData) { - if (useChannelBinding) { - channelBindingHeader = createByteArray("p=tls-unique"); - } - else { - channelBindingHeader = createByteArray("y"); - } - } - return concat(channelBindingHeader, createByteArray(","), (getAuthorizationID().empty() ? ByteArray() : createByteArray("a=" + escape(getAuthorizationID()))), createByteArray(",")); + ByteArray channelBindingHeader(createByteArray("n")); + if (tlsChannelBindingData) { + if (useChannelBinding) { + channelBindingHeader = createByteArray("p=tls-unique"); + } + else { + channelBindingHeader = createByteArray("y"); + } + } + return concat(channelBindingHeader, createByteArray(","), (getAuthorizationID().empty() ? ByteArray() : createByteArray("a=" + escape(getAuthorizationID()))), createByteArray(",")); } void SCRAMSHA1ClientAuthenticator::setTLSChannelBindingData(const ByteArray& channelBindingData) { - this->tlsChannelBindingData = channelBindingData; + this->tlsChannelBindingData = channelBindingData; } ByteArray SCRAMSHA1ClientAuthenticator::getFinalMessageWithoutProof() const { - ByteArray channelBindData; - if (useChannelBinding && tlsChannelBindingData) { - channelBindData = *tlsChannelBindingData; - } - return concat(createByteArray("c=" + Base64::encode(concat(getGS2Header(), channelBindData)) + ",r=" + clientnonce), serverNonce); + ByteArray channelBindData; + if (useChannelBinding && tlsChannelBindingData) { + channelBindData = *tlsChannelBindingData; + } + return concat(createByteArray("c=" + Base64::encode(concat(getGS2Header(), channelBindData)) + ",r=" + clientnonce), serverNonce); } |