summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/Client/ClientSession.cpp')
-rw-r--r--Swiften/Client/ClientSession.cpp776
1 files changed, 388 insertions, 388 deletions
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index 52b8cfb..e38dde8 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -51,35 +51,35 @@
#endif
#define CHECK_STATE_OR_RETURN(a) \
- if (!checkState(a)) { return; }
+ if (!checkState(a)) { return; }
namespace Swift {
ClientSession::ClientSession(
- const JID& jid,
- boost::shared_ptr<SessionStream> stream,
- IDNConverter* idnConverter,
- CryptoProvider* crypto) :
- localJID(jid),
- state(Initial),
- stream(stream),
- idnConverter(idnConverter),
- crypto(crypto),
- allowPLAINOverNonTLS(false),
- useStreamCompression(true),
- useTLS(UseTLSWhenAvailable),
- useAcks(true),
- needSessionStart(false),
- needResourceBind(false),
- needAcking(false),
- rosterVersioningSupported(false),
- authenticator(NULL),
- certificateTrustChecker(NULL),
- singleSignOn(false),
- authenticationPort(-1) {
+ const JID& jid,
+ boost::shared_ptr<SessionStream> stream,
+ IDNConverter* idnConverter,
+ CryptoProvider* crypto) :
+ localJID(jid),
+ state(Initial),
+ stream(stream),
+ idnConverter(idnConverter),
+ crypto(crypto),
+ allowPLAINOverNonTLS(false),
+ useStreamCompression(true),
+ useTLS(UseTLSWhenAvailable),
+ useAcks(true),
+ needSessionStart(false),
+ needResourceBind(false),
+ needAcking(false),
+ rosterVersioningSupported(false),
+ authenticator(NULL),
+ certificateTrustChecker(NULL),
+ singleSignOn(false),
+ authenticationPort(-1) {
#ifdef SWIFTEN_PLATFORM_WIN32
if (WindowsRegistry::isFIPSEnabled()) {
- SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable." << std::endl;
+ SWIFT_LOG(info) << "Windows is running in FIPS-140 mode. Some authentication methods will be unavailable." << std::endl;
}
#endif
}
@@ -88,427 +88,427 @@ ClientSession::~ClientSession() {
}
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->onClosed.connect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1));
- stream->onTLSEncrypted.connect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this()));
-
- assert(state == Initial);
- state = WaitingForStreamStart;
- sendStreamHeader();
+ stream->onStreamStartReceived.connect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1));
+ stream->onElementReceived.connect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1));
+ stream->onClosed.connect(boost::bind(&ClientSession::handleStreamClosed, 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);
+ ProtocolHeader header;
+ header.setTo(getRemoteJID());
+ stream->writeHeader(header);
}
void ClientSession::sendStanza(boost::shared_ptr<Stanza> stanza) {
- stream->writeElement(stanza);
- if (stanzaAckRequester_) {
- stanzaAckRequester_->handleStanzaSent(stanza);
- }
+ stream->writeElement(stanza);
+ if (stanzaAckRequester_) {
+ stanzaAckRequester_->handleStanzaSent(stanza);
+ }
}
void ClientSession::handleStreamStart(const ProtocolHeader&) {
- CHECK_STATE_OR_RETURN(WaitingForStreamStart);
- state = Negotiating;
+ CHECK_STATE_OR_RETURN(WaitingForStreamStart);
+ state = Negotiating;
}
void ClientSession::handleElement(boost::shared_ptr<ToplevelElement> element) {
- if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) {
- if (stanzaAckResponder_) {
- stanzaAckResponder_->handleStanzaReceived();
- }
- if (getState() == Initialized) {
- onStanzaReceived(stanza);
- }
- else if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(element)) {
- 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);
- }
- needResourceBind = false;
- continueSessionInitialization();
- }
- else {
- finishSession(Error::UnexpectedElementError);
- }
- }
- else if (state == StartingSession) {
- if (iq->getType() == IQ::Result) {
- needSessionStart = false;
- continueSessionInitialization();
- }
- else if (iq->getType() == IQ::Error) {
- finishSession(Error::SessionStartError);
- }
- else {
- finishSession(Error::UnexpectedElementError);
- }
- }
- else {
- finishSession(Error::UnexpectedElementError);
- }
- }
- }
- else if (boost::dynamic_pointer_cast<StanzaAckRequest>(element)) {
- if (stanzaAckResponder_) {
- stanzaAckResponder_->handleAckRequestReceived();
- }
- }
- else if (boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(element)) {
- if (stanzaAckRequester_) {
- if (ack->isValid()) {
- stanzaAckRequester_->handleAckReceived(ack->getHandledStanzasCount());
- }
- else {
- SWIFT_LOG(warning) << "Got invalid ack from server";
- }
- }
- else {
- SWIFT_LOG(warning) << "Ignoring ack";
- }
- }
- else if (StreamError::ref streamError = boost::dynamic_pointer_cast<StreamError>(element)) {
- finishSession(Error::StreamError);
- }
- else if (getState() == Initialized) {
- boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element);
- if (stanza) {
- if (stanzaAckResponder_) {
- stanzaAckResponder_->handleStanzaReceived();
- }
- onStanzaReceived(stanza);
- }
- }
- else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) {
- CHECK_STATE_OR_RETURN(Negotiating);
-
- if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption() && useTLS != NeverUseTLS) {
- state = WaitingForEncrypt;
- stream->writeElement(boost::make_shared<StartTLSRequest>());
- }
- else if (useTLS == RequireTLS && !stream->isTLSEncrypted()) {
- finishSession(Error::NoSupportedAuthMechanismsError);
- }
- else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) {
- state = Compressing;
- stream->writeElement(boost::make_shared<CompressRequest>("zlib"));
- }
- else if (streamFeatures->hasAuthenticationMechanisms()) {
+ if (boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element)) {
+ if (stanzaAckResponder_) {
+ stanzaAckResponder_->handleStanzaReceived();
+ }
+ if (getState() == Initialized) {
+ onStanzaReceived(stanza);
+ }
+ else if (boost::shared_ptr<IQ> iq = boost::dynamic_pointer_cast<IQ>(element)) {
+ 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);
+ }
+ needResourceBind = false;
+ continueSessionInitialization();
+ }
+ else {
+ finishSession(Error::UnexpectedElementError);
+ }
+ }
+ else if (state == StartingSession) {
+ if (iq->getType() == IQ::Result) {
+ needSessionStart = false;
+ continueSessionInitialization();
+ }
+ else if (iq->getType() == IQ::Error) {
+ finishSession(Error::SessionStartError);
+ }
+ else {
+ finishSession(Error::UnexpectedElementError);
+ }
+ }
+ else {
+ finishSession(Error::UnexpectedElementError);
+ }
+ }
+ }
+ else if (boost::dynamic_pointer_cast<StanzaAckRequest>(element)) {
+ if (stanzaAckResponder_) {
+ stanzaAckResponder_->handleAckRequestReceived();
+ }
+ }
+ else if (boost::shared_ptr<StanzaAck> ack = boost::dynamic_pointer_cast<StanzaAck>(element)) {
+ if (stanzaAckRequester_) {
+ if (ack->isValid()) {
+ stanzaAckRequester_->handleAckReceived(ack->getHandledStanzasCount());
+ }
+ else {
+ SWIFT_LOG(warning) << "Got invalid ack from server";
+ }
+ }
+ else {
+ SWIFT_LOG(warning) << "Ignoring ack";
+ }
+ }
+ else if (StreamError::ref streamError = boost::dynamic_pointer_cast<StreamError>(element)) {
+ finishSession(Error::StreamError);
+ }
+ else if (getState() == Initialized) {
+ boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element);
+ if (stanza) {
+ if (stanzaAckResponder_) {
+ stanzaAckResponder_->handleStanzaReceived();
+ }
+ onStanzaReceived(stanza);
+ }
+ }
+ else if (StreamFeatures* streamFeatures = dynamic_cast<StreamFeatures*>(element.get())) {
+ CHECK_STATE_OR_RETURN(Negotiating);
+
+ if (streamFeatures->hasStartTLS() && stream->supportsTLSEncryption() && useTLS != NeverUseTLS) {
+ state = WaitingForEncrypt;
+ stream->writeElement(boost::make_shared<StartTLSRequest>());
+ }
+ else if (useTLS == RequireTLS && !stream->isTLSEncrypted()) {
+ finishSession(Error::NoSupportedAuthMechanismsError);
+ }
+ else if (useStreamCompression && stream->supportsZLibCompression() && streamFeatures->hasCompressionMethod("zlib")) {
+ state = Compressing;
+ stream->writeElement(boost::make_shared<CompressRequest>("zlib"));
+ }
+ else if (streamFeatures->hasAuthenticationMechanisms()) {
#ifdef SWIFTEN_PLATFORM_WIN32
- if (singleSignOn) {
- const boost::optional<std::string> authenticationHostname = streamFeatures->getAuthenticationHostname();
- bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI") && authenticationHostname && !authenticationHostname->empty();
-
- if (!gssapiSupported) {
- finishSession(Error::NoSupportedAuthMechanismsError);
- }
- else {
- WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(*authenticationHostname, localJID.getDomain(), authenticationPort);
- boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError);
-
- authenticator = gssapiAuthenticator;
-
- if (!gssapiAuthenticator->isError()) {
- state = Authenticating;
- stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse()));
- }
- else {
- error->errorCode = gssapiAuthenticator->getErrorCode();
- finishSession(error);
- }
- }
- }
- else
+ if (singleSignOn) {
+ const boost::optional<std::string> authenticationHostname = streamFeatures->getAuthenticationHostname();
+ bool gssapiSupported = streamFeatures->hasAuthenticationMechanism("GSSAPI") && authenticationHostname && !authenticationHostname->empty();
+
+ if (!gssapiSupported) {
+ finishSession(Error::NoSupportedAuthMechanismsError);
+ }
+ else {
+ WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = new WindowsGSSAPIClientAuthenticator(*authenticationHostname, localJID.getDomain(), authenticationPort);
+ boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError);
+
+ authenticator = gssapiAuthenticator;
+
+ if (!gssapiAuthenticator->isError()) {
+ state = Authenticating;
+ stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse()));
+ }
+ else {
+ error->errorCode = gssapiAuthenticator->getErrorCode();
+ finishSession(error);
+ }
+ }
+ }
+ else
#endif
- if (stream->hasTLSCertificate()) {
- if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
- authenticator = new EXTERNALClientAuthenticator();
- state = Authenticating;
- stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray("")));
- }
- else {
- finishSession(Error::TLSClientCertificateError);
- }
- }
- else if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
- authenticator = new EXTERNALClientAuthenticator();
- state = Authenticating;
- stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray("")));
- }
- else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1") || streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS")) {
- std::ostringstream s;
- ByteArray finishMessage;
- bool plus = streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS");
- if (stream->isTLSEncrypted()) {
- finishMessage = stream->getTLSFinishMessage();
- plus &= !finishMessage.empty();
- }
- s << boost::uuids::random_generator()();
- SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter, crypto);
- if (!finishMessage.empty()) {
- scramAuthenticator->setTLSChannelBindingData(finishMessage);
- }
- authenticator = scramAuthenticator;
- state = WaitingForCredentials;
- onNeedCredentials();
- }
- else if ((stream->isTLSEncrypted() || allowPLAINOverNonTLS) && streamFeatures->hasAuthenticationMechanism("PLAIN")) {
- authenticator = new PLAINClientAuthenticator();
- state = WaitingForCredentials;
- onNeedCredentials();
- }
- else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && crypto->isMD5AllowedForCrypto()) {
- std::ostringstream s;
- s << boost::uuids::random_generator()();
- // FIXME: Host should probably be the actual host
- authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str(), crypto);
- state = WaitingForCredentials;
- onNeedCredentials();
- }
- else {
- finishSession(Error::NoSupportedAuthMechanismsError);
- }
- }
- else {
- // Start the session
- rosterVersioningSupported = streamFeatures->hasRosterVersioning();
- stream->setWhitespacePingEnabled(true);
- needSessionStart = streamFeatures->hasSession();
- needResourceBind = streamFeatures->hasResourceBind();
- needAcking = streamFeatures->hasStreamManagement() && useAcks;
- if (!needResourceBind) {
- // Resource binding is a MUST
- finishSession(Error::ResourceBindError);
- }
- else {
- continueSessionInitialization();
- }
- }
- }
- else if (boost::dynamic_pointer_cast<Compressed>(element)) {
- CHECK_STATE_OR_RETURN(Compressing);
- state = WaitingForStreamStart;
- stream->addZLibCompression();
- stream->resetXMPPParser();
- sendStreamHeader();
- }
- else if (boost::dynamic_pointer_cast<CompressFailure>(element)) {
- finishSession(Error::CompressionFailedError);
- }
- else if (boost::dynamic_pointer_cast<StreamManagementEnabled>(element)) {
- stanzaAckRequester_ = boost::make_shared<StanzaAckRequester>();
- stanzaAckRequester_->onRequestAck.connect(boost::bind(&ClientSession::requestAck, shared_from_this()));
- stanzaAckRequester_->onStanzaAcked.connect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1));
- stanzaAckResponder_ = boost::make_shared<StanzaAckResponder>();
- stanzaAckResponder_->onAck.connect(boost::bind(&ClientSession::ack, shared_from_this(), _1));
- needAcking = false;
- continueSessionInitialization();
- }
- else if (boost::dynamic_pointer_cast<StreamManagementFailed>(element)) {
- needAcking = false;
- continueSessionInitialization();
- }
- else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) {
- CHECK_STATE_OR_RETURN(Authenticating);
- assert(authenticator);
- if (authenticator->setChallenge(challenge->getValue())) {
- stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse()));
- }
+ if (stream->hasTLSCertificate()) {
+ if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
+ authenticator = new EXTERNALClientAuthenticator();
+ state = Authenticating;
+ stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray("")));
+ }
+ else {
+ finishSession(Error::TLSClientCertificateError);
+ }
+ }
+ else if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
+ authenticator = new EXTERNALClientAuthenticator();
+ state = Authenticating;
+ stream->writeElement(boost::make_shared<AuthRequest>("EXTERNAL", createSafeByteArray("")));
+ }
+ else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1") || streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS")) {
+ std::ostringstream s;
+ ByteArray finishMessage;
+ bool plus = streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1-PLUS");
+ if (stream->isTLSEncrypted()) {
+ finishMessage = stream->getTLSFinishMessage();
+ plus &= !finishMessage.empty();
+ }
+ s << boost::uuids::random_generator()();
+ SCRAMSHA1ClientAuthenticator* scramAuthenticator = new SCRAMSHA1ClientAuthenticator(s.str(), plus, idnConverter, crypto);
+ if (!finishMessage.empty()) {
+ scramAuthenticator->setTLSChannelBindingData(finishMessage);
+ }
+ authenticator = scramAuthenticator;
+ state = WaitingForCredentials;
+ onNeedCredentials();
+ }
+ else if ((stream->isTLSEncrypted() || allowPLAINOverNonTLS) && streamFeatures->hasAuthenticationMechanism("PLAIN")) {
+ authenticator = new PLAINClientAuthenticator();
+ state = WaitingForCredentials;
+ onNeedCredentials();
+ }
+ else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5") && crypto->isMD5AllowedForCrypto()) {
+ std::ostringstream s;
+ s << boost::uuids::random_generator()();
+ // FIXME: Host should probably be the actual host
+ authenticator = new DIGESTMD5ClientAuthenticator(localJID.getDomain(), s.str(), crypto);
+ state = WaitingForCredentials;
+ onNeedCredentials();
+ }
+ else {
+ finishSession(Error::NoSupportedAuthMechanismsError);
+ }
+ }
+ else {
+ // Start the session
+ rosterVersioningSupported = streamFeatures->hasRosterVersioning();
+ stream->setWhitespacePingEnabled(true);
+ needSessionStart = streamFeatures->hasSession();
+ needResourceBind = streamFeatures->hasResourceBind();
+ needAcking = streamFeatures->hasStreamManagement() && useAcks;
+ if (!needResourceBind) {
+ // Resource binding is a MUST
+ finishSession(Error::ResourceBindError);
+ }
+ else {
+ continueSessionInitialization();
+ }
+ }
+ }
+ else if (boost::dynamic_pointer_cast<Compressed>(element)) {
+ CHECK_STATE_OR_RETURN(Compressing);
+ state = WaitingForStreamStart;
+ stream->addZLibCompression();
+ stream->resetXMPPParser();
+ sendStreamHeader();
+ }
+ else if (boost::dynamic_pointer_cast<CompressFailure>(element)) {
+ finishSession(Error::CompressionFailedError);
+ }
+ else if (boost::dynamic_pointer_cast<StreamManagementEnabled>(element)) {
+ stanzaAckRequester_ = boost::make_shared<StanzaAckRequester>();
+ stanzaAckRequester_->onRequestAck.connect(boost::bind(&ClientSession::requestAck, shared_from_this()));
+ stanzaAckRequester_->onStanzaAcked.connect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1));
+ stanzaAckResponder_ = boost::make_shared<StanzaAckResponder>();
+ stanzaAckResponder_->onAck.connect(boost::bind(&ClientSession::ack, shared_from_this(), _1));
+ needAcking = false;
+ continueSessionInitialization();
+ }
+ else if (boost::dynamic_pointer_cast<StreamManagementFailed>(element)) {
+ needAcking = false;
+ continueSessionInitialization();
+ }
+ else if (AuthChallenge* challenge = dynamic_cast<AuthChallenge*>(element.get())) {
+ CHECK_STATE_OR_RETURN(Authenticating);
+ assert(authenticator);
+ if (authenticator->setChallenge(challenge->getValue())) {
+ stream->writeElement(boost::make_shared<AuthResponse>(authenticator->getResponse()));
+ }
#ifdef SWIFTEN_PLATFORM_WIN32
- else if (WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = dynamic_cast<WindowsGSSAPIClientAuthenticator*>(authenticator)) {
- boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError);
+ else if (WindowsGSSAPIClientAuthenticator* gssapiAuthenticator = dynamic_cast<WindowsGSSAPIClientAuthenticator*>(authenticator)) {
+ boost::shared_ptr<Error> error = boost::make_shared<Error>(Error::AuthenticationFailedError);
- error->errorCode = gssapiAuthenticator->getErrorCode();
- finishSession(error);
- }
+ error->errorCode = gssapiAuthenticator->getErrorCode();
+ finishSession(error);
+ }
#endif
- else {
- finishSession(Error::AuthenticationFailedError);
- }
- }
- else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) {
- CHECK_STATE_OR_RETURN(Authenticating);
- assert(authenticator);
- if (!authenticator->setChallenge(authSuccess->getValue())) {
- finishSession(Error::ServerVerificationFailedError);
- }
- else {
- state = WaitingForStreamStart;
- delete authenticator;
- authenticator = NULL;
- stream->resetXMPPParser();
- sendStreamHeader();
- }
- }
- else if (dynamic_cast<AuthFailure*>(element.get())) {
- finishSession(Error::AuthenticationFailedError);
- }
- else if (dynamic_cast<TLSProceed*>(element.get())) {
- CHECK_STATE_OR_RETURN(WaitingForEncrypt);
- state = Encrypting;
- stream->addTLSEncryption();
- }
- else if (dynamic_cast<StartTLSFailure*>(element.get())) {
- finishSession(Error::TLSError);
- }
- else {
- // FIXME Not correct?
- state = Initialized;
- onInitialized();
- }
+ else {
+ finishSession(Error::AuthenticationFailedError);
+ }
+ }
+ else if (AuthSuccess* authSuccess = dynamic_cast<AuthSuccess*>(element.get())) {
+ CHECK_STATE_OR_RETURN(Authenticating);
+ assert(authenticator);
+ if (!authenticator->setChallenge(authSuccess->getValue())) {
+ finishSession(Error::ServerVerificationFailedError);
+ }
+ else {
+ state = WaitingForStreamStart;
+ delete authenticator;
+ authenticator = NULL;
+ stream->resetXMPPParser();
+ sendStreamHeader();
+ }
+ }
+ else if (dynamic_cast<AuthFailure*>(element.get())) {
+ finishSession(Error::AuthenticationFailedError);
+ }
+ else if (dynamic_cast<TLSProceed*>(element.get())) {
+ CHECK_STATE_OR_RETURN(WaitingForEncrypt);
+ state = Encrypting;
+ stream->addTLSEncryption();
+ }
+ else if (dynamic_cast<StartTLSFailure*>(element.get())) {
+ finishSession(Error::TLSError);
+ }
+ else {
+ // FIXME Not correct?
+ state = Initialized;
+ onInitialized();
+ }
}
void ClientSession::continueSessionInitialization() {
- if (needResourceBind) {
- state = BindingResource;
- boost::shared_ptr<ResourceBind> resourceBind(boost::make_shared<ResourceBind>());
- if (!localJID.getResource().empty()) {
- resourceBind->setResource(localJID.getResource());
- }
- sendStanza(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind));
- }
- else if (needAcking) {
- state = EnablingSessionManagement;
- stream->writeElement(boost::make_shared<EnableStreamManagement>());
- }
- else if (needSessionStart) {
- state = StartingSession;
- sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", boost::make_shared<StartSession>()));
- }
- else {
- state = Initialized;
- onInitialized();
- }
+ if (needResourceBind) {
+ state = BindingResource;
+ boost::shared_ptr<ResourceBind> resourceBind(boost::make_shared<ResourceBind>());
+ if (!localJID.getResource().empty()) {
+ resourceBind->setResource(localJID.getResource());
+ }
+ sendStanza(IQ::createRequest(IQ::Set, JID(), "session-bind", resourceBind));
+ }
+ else if (needAcking) {
+ state = EnablingSessionManagement;
+ stream->writeElement(boost::make_shared<EnableStreamManagement>());
+ }
+ else if (needSessionStart) {
+ state = StartingSession;
+ sendStanza(IQ::createRequest(IQ::Set, JID(), "session-start", boost::make_shared<StartSession>()));
+ }
+ else {
+ state = Initialized;
+ onInitialized();
+ }
}
bool ClientSession::checkState(State state) {
- if (this->state != state) {
- finishSession(Error::UnexpectedElementError);
- return false;
- }
- return true;
+ if (this->state != state) {
+ finishSession(Error::UnexpectedElementError);
+ return false;
+ }
+ return true;
}
void ClientSession::sendCredentials(const SafeByteArray& password) {
- assert(WaitingForCredentials);
- assert(authenticator);
- state = Authenticating;
- authenticator->setCredentials(localJID.getNode(), password);
- stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse()));
+ assert(WaitingForCredentials);
+ assert(authenticator);
+ state = Authenticating;
+ authenticator->setCredentials(localJID.getNode(), password);
+ stream->writeElement(boost::make_shared<AuthRequest>(authenticator->getName(), authenticator->getResponse()));
}
void ClientSession::handleTLSEncrypted() {
- CHECK_STATE_OR_RETURN(Encrypting);
-
- std::vector<Certificate::ref> certificateChain = stream->getPeerCertificateChain();
- boost::shared_ptr<CertificateVerificationError> verificationError = stream->getPeerCertificateVerificationError();
- if (verificationError) {
- checkTrustOrFinish(certificateChain, verificationError);
- }
- else {
- ServerIdentityVerifier identityVerifier(localJID, idnConverter);
- if (!certificateChain.empty() && identityVerifier.certificateVerifies(certificateChain[0])) {
- continueAfterTLSEncrypted();
- }
- else {
- checkTrustOrFinish(certificateChain, boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity));
- }
- }
+ CHECK_STATE_OR_RETURN(Encrypting);
+
+ std::vector<Certificate::ref> certificateChain = stream->getPeerCertificateChain();
+ boost::shared_ptr<CertificateVerificationError> verificationError = stream->getPeerCertificateVerificationError();
+ if (verificationError) {
+ checkTrustOrFinish(certificateChain, verificationError);
+ }
+ else {
+ ServerIdentityVerifier identityVerifier(localJID, idnConverter);
+ if (!certificateChain.empty() && identityVerifier.certificateVerifies(certificateChain[0])) {
+ continueAfterTLSEncrypted();
+ }
+ else {
+ checkTrustOrFinish(certificateChain, boost::make_shared<CertificateVerificationError>(CertificateVerificationError::InvalidServerIdentity));
+ }
+ }
}
void ClientSession::checkTrustOrFinish(const std::vector<Certificate::ref>& certificateChain, boost::shared_ptr<CertificateVerificationError> error) {
- if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificateChain)) {
- continueAfterTLSEncrypted();
- }
- else {
- finishSession(error);
- }
+ if (certificateTrustChecker && certificateTrustChecker->isCertificateTrusted(certificateChain)) {
+ continueAfterTLSEncrypted();
+ }
+ else {
+ finishSession(error);
+ }
}
void ClientSession::continueAfterTLSEncrypted() {
- state = WaitingForStreamStart;
- stream->resetXMPPParser();
- sendStreamHeader();
+ state = WaitingForStreamStart;
+ stream->resetXMPPParser();
+ sendStreamHeader();
}
void ClientSession::handleStreamClosed(boost::shared_ptr<Swift::Error> streamError) {
- State previousState = state;
- state = Finished;
-
- if (stanzaAckRequester_) {
- stanzaAckRequester_->onRequestAck.disconnect(boost::bind(&ClientSession::requestAck, shared_from_this()));
- stanzaAckRequester_->onStanzaAcked.disconnect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1));
- stanzaAckRequester_.reset();
- }
- if (stanzaAckResponder_) {
- stanzaAckResponder_->onAck.disconnect(boost::bind(&ClientSession::ack, shared_from_this(), _1));
- stanzaAckResponder_.reset();
- }
- stream->setWhitespacePingEnabled(false);
- stream->onStreamStartReceived.disconnect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1));
- stream->onElementReceived.disconnect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1));
- stream->onClosed.disconnect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1));
- stream->onTLSEncrypted.disconnect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this()));
-
- if (previousState == Finishing) {
- onFinished(error_);
- }
- else {
- onFinished(streamError);
- }
+ State previousState = state;
+ state = Finished;
+
+ if (stanzaAckRequester_) {
+ stanzaAckRequester_->onRequestAck.disconnect(boost::bind(&ClientSession::requestAck, shared_from_this()));
+ stanzaAckRequester_->onStanzaAcked.disconnect(boost::bind(&ClientSession::handleStanzaAcked, shared_from_this(), _1));
+ stanzaAckRequester_.reset();
+ }
+ if (stanzaAckResponder_) {
+ stanzaAckResponder_->onAck.disconnect(boost::bind(&ClientSession::ack, shared_from_this(), _1));
+ stanzaAckResponder_.reset();
+ }
+ stream->setWhitespacePingEnabled(false);
+ stream->onStreamStartReceived.disconnect(boost::bind(&ClientSession::handleStreamStart, shared_from_this(), _1));
+ stream->onElementReceived.disconnect(boost::bind(&ClientSession::handleElement, shared_from_this(), _1));
+ stream->onClosed.disconnect(boost::bind(&ClientSession::handleStreamClosed, shared_from_this(), _1));
+ stream->onTLSEncrypted.disconnect(boost::bind(&ClientSession::handleTLSEncrypted, shared_from_this()));
+
+ if (previousState == Finishing) {
+ onFinished(error_);
+ }
+ else {
+ onFinished(streamError);
+ }
}
void ClientSession::finish() {
- finishSession(boost::shared_ptr<Error>());
+ finishSession(boost::shared_ptr<Error>());
}
void ClientSession::finishSession(Error::Type error) {
- finishSession(boost::make_shared<Swift::ClientSession::Error>(error));
+ finishSession(boost::make_shared<Swift::ClientSession::Error>(error));
}
void ClientSession::finishSession(boost::shared_ptr<Swift::Error> error) {
- state = Finishing;
- if (!error_) {
- error_ = error;
- }
- else {
- SWIFT_LOG(warning) << "Session finished twice";
- }
- assert(stream->isOpen());
- if (stanzaAckResponder_) {
- stanzaAckResponder_->handleAckRequestReceived();
- }
- if (authenticator) {
- delete authenticator;
- authenticator = NULL;
- }
- stream->writeFooter();
- stream->close();
+ state = Finishing;
+ if (!error_) {
+ error_ = error;
+ }
+ else {
+ SWIFT_LOG(warning) << "Session finished twice";
+ }
+ assert(stream->isOpen());
+ if (stanzaAckResponder_) {
+ stanzaAckResponder_->handleAckRequestReceived();
+ }
+ if (authenticator) {
+ delete authenticator;
+ authenticator = NULL;
+ }
+ stream->writeFooter();
+ stream->close();
}
void ClientSession::requestAck() {
- stream->writeElement(boost::make_shared<StanzaAckRequest>());
+ stream->writeElement(boost::make_shared<StanzaAckRequest>());
}
void ClientSession::handleStanzaAcked(boost::shared_ptr<Stanza> stanza) {
- onStanzaAcked(stanza);
+ onStanzaAcked(stanza);
}
void ClientSession::ack(unsigned int handledStanzasCount) {
- stream->writeElement(boost::make_shared<StanzaAck>(handledStanzasCount));
+ stream->writeElement(boost::make_shared<StanzaAck>(handledStanzasCount));
}
}