diff options
| author | Remko Tronçon <git@el-tramo.be> | 2009-11-20 22:53:40 (GMT) |
|---|---|---|
| committer | Remko Tronçon <git@el-tramo.be> | 2009-11-20 22:53:40 (GMT) |
| commit | 4417a63a1acdf5f6e78655e8ae377bc24d5d8f02 (patch) | |
| tree | 0c682fcc582a9f1181f436d5e5d98180fdf5387a /Swiften | |
| parent | 4e944a225d91ff4622e50186120ef0bbbb3a1d69 (diff) | |
| download | swift-4417a63a1acdf5f6e78655e8ae377bc24d5d8f02.zip swift-4417a63a1acdf5f6e78655e8ae377bc24d5d8f02.tar.bz2 | |
Implement SCRAM-SHA1.
Actually found out that I implemented the old RFC. Need to reimplement
SCRAM-SHA1 from scratch based on
http://tools.ietf.org/html/draft-ietf-sasl-scram-10
Disabling for now.
Diffstat (limited to 'Swiften')
| -rw-r--r-- | Swiften/Client/ClientSession.cpp | 19 | ||||
| -rw-r--r-- | Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp | 2 |
2 files changed, 20 insertions, 1 deletions
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp index 06a7617..f4c4a22 100644 --- a/Swiften/Client/ClientSession.cpp +++ b/Swiften/Client/ClientSession.cpp @@ -1,161 +1,180 @@ #include "Swiften/Client/ClientSession.h" #include <boost/bind.hpp> #include "Swiften/Elements/ProtocolHeader.h" #include "Swiften/Elements/StreamFeatures.h" #include "Swiften/Elements/StartTLSRequest.h" #include "Swiften/Elements/StartTLSFailure.h" #include "Swiften/Elements/TLSProceed.h" #include "Swiften/Elements/AuthRequest.h" #include "Swiften/Elements/AuthSuccess.h" #include "Swiften/Elements/AuthFailure.h" +#include "Swiften/Elements/AuthChallenge.h" +#include "Swiften/Elements/AuthResponse.h" #include "Swiften/Elements/StartSession.h" #include "Swiften/Elements/IQ.h" #include "Swiften/Elements/ResourceBind.h" #include "Swiften/SASL/PLAINClientAuthenticator.h" +#include "Swiften/SASL/SCRAMSHA1ClientAuthenticator.h" #include "Swiften/Session/SessionStream.h" namespace Swift { ClientSession::ClientSession( const JID& jid, boost::shared_ptr<SessionStream> stream) : localJID(jid), state(Initial), stream(stream), needSessionStart(false), authenticator(NULL) { } void ClientSession::start() { stream->onStreamStartReceived.connect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1)); stream->onElementReceived.connect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1)); stream->onError.connect(boost::bind(&ClientSession::handleStreamError, shared_from_this(), _1)); stream->onTLSEncrypted.connect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this())); assert(state == Initial); state = WaitingForStreamStart; sendStreamHeader(); } void ClientSession::sendStreamHeader() { ProtocolHeader header; header.setTo(getRemoteJID()); stream->writeHeader(header); } void ClientSession::sendElement(boost::shared_ptr<Element> element) { stream->writeElement(element); } void ClientSession::handleStreamStart(const ProtocolHeader&) { checkState(WaitingForStreamStart); state = Negotiating; } void ClientSession::handleElement(boost::shared_ptr<Element> element) { if (getState() == Initialized) { onElementReceived(element); } else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) { if (!checkState(Negotiating)) { return; } if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption()) { state = WaitingForEncrypt; stream->writeElement(boost::shared_ptr<StartTLSRequest>(new StartTLSRequest())); } else if (streamFeatures->hasAuthenticationMechanisms()) { if (stream->hasTLSCertificate()) { if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) { state = Authenticating; stream->writeElement(boost::shared_ptr<Element>(new AuthRequest("EXTERNAL", ""))); } else { finishSession(Error::TLSClientCertificateError); } } + /*else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1")) { + // FIXME: Use a real nonce + authenticator = new SCRAMSHA1ClientAuthenticator(ByteArray("\x01\x02\x03\x04\x05\x06\x07\x08", 8)); + state = WaitingForCredentials; + onNeedCredentials(); + }*/ else if (streamFeatures->hasAuthenticationMechanism("PLAIN")) { authenticator = new PLAINClientAuthenticator(); state = WaitingForCredentials; onNeedCredentials(); } else { finishSession(Error::NoSupportedAuthMechanismsError); } } else { // Start the session stream->setWhitespacePingEnabled(true); if (streamFeatures->hasSession()) { needSessionStart = true; } if (streamFeatures->hasResourceBind()) { state = BindingResource; boost::shared_ptr<ResourceBind> resourceBind(new ResourceBind()); if (!localJID.getResource().isEmpty()) { resourceBind->setResource(localJID.getResource()); } stream->writeElement(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind)); } else if (needSessionStart) { sendSessionStart(); } else { state = Initialized; onInitialized(); } } } + else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) { + checkState(Authenticating); + assert(authenticator); + if (authenticator->setChallenge(challenge->getValue())) { + stream->writeElement(boost::shared_ptr<AuthResponse>(new AuthResponse(authenticator->getResponse()))); + } + else { + finishSession(Error::AuthenticationFailedError); + } + } else if (dynamic_cast<AuthSuccess*>(element.get())) { checkState(Authenticating); state = WaitingForStreamStart; delete authenticator; authenticator = NULL; stream->resetXMPPParser(); sendStreamHeader(); } else if (dynamic_cast<AuthFailure*>(element.get())) { delete authenticator; authenticator = NULL; finishSession(Error::AuthenticationFailedError); } else if (dynamic_cast<TLSProceed*>(element.get())) { checkState(WaitingForEncrypt); state = Encrypting; stream->addTLSEncryption(); } else if (dynamic_cast<StartTLSFailure*>(element.get())) { finishSession(Error::TLSError); } else if (IQ* iq = dynamic_cast<IQ*>(element.get())) { if (state == BindingResource) { boost::shared_ptr<ResourceBind> resourceBind(iq->getPayload<ResourceBind>()); if (iq->getType() == IQ::Error && iq->getID() == "session-bind") { finishSession(Error::ResourceBindError); } else if (!resourceBind) { finishSession(Error::UnexpectedElementError); } else if (iq->getType() == IQ::Result) { localJID = resourceBind->getJID(); if (!localJID.isValid()) { finishSession(Error::ResourceBindError); } if (needSessionStart) { sendSessionStart(); } else { state = Initialized; } } else { finishSession(Error::UnexpectedElementError); } } else if (state == StartingSession) { if (iq->getType() == IQ::Result) { diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp index 3109f56..f5c55c0 100644 --- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp +++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp @@ -1,56 +1,56 @@ #include "Swiften/SASL/SCRAMSHA1ClientAuthenticator.h" #include <cassert> #include "Swiften/StringCodecs/SHA1.h" #include "Swiften/StringCodecs/HMACSHA1.h" namespace Swift { -SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const ByteArray& nonce) : ClientAuthenticator("SCRAM-SHA1"), step(Initial), clientnonce(nonce) { +SCRAMSHA1ClientAuthenticator::SCRAMSHA1ClientAuthenticator(const ByteArray& nonce) : ClientAuthenticator("SCRAM-SHA-1"), step(Initial), clientnonce(nonce) { } ByteArray SCRAMSHA1ClientAuthenticator::getResponse() const { if (step == Initial) { return getInitialClientMessage(); } else { ByteArray mask = HMACSHA1::getResult(getClientVerifier(), initialServerMessage + getInitialClientMessage()); ByteArray p = SHA1::getBinaryHash(getPassword()); for (unsigned int i = 0; i < p.getSize(); ++i) { p[i] ^= mask[i]; } return p; } } bool SCRAMSHA1ClientAuthenticator::setChallenge(const ByteArray& response) { if (step == Initial) { initialServerMessage = response; step = Proof; return getSalt().getSize() > 0; } else { return response == HMACSHA1::getResult(getClientVerifier(), getInitialClientMessage() + initialServerMessage); } } ByteArray SCRAMSHA1ClientAuthenticator::getSalt() const { if (initialServerMessage.getSize() < 8) { std::cerr << "ERROR: SCRAM-SHA1: Invalid server response" << std::endl; return ByteArray(); } else { return ByteArray(initialServerMessage.getData(), 8); } } ByteArray SCRAMSHA1ClientAuthenticator::getClientVerifier() const { return HMACSHA1::getResult(SHA1::getBinaryHash(getPassword()), getSalt()); } ByteArray SCRAMSHA1ClientAuthenticator::getInitialClientMessage() const { return ByteArray(getAuthorizationID()) + '\0' + ByteArray(getAuthenticationID()) + '\0' + ByteArray(clientnonce); } } |
Swift