From eb6a3e659254de70b7c45627e7e0f4f53b737d04 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Sat, 8 May 2010 19:01:12 +0200
Subject: Don't allow PLAIN over Non-TLS.


diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index a255cef..5e2cd84 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -40,6 +40,7 @@ ClientSession::ClientSession(
 			localJID(jid),	
 			state(Initial), 
 			stream(stream),
+			allowPLAINOverNonTLS(false),
 			needSessionStart(false),
 			authenticator(NULL) {
 }
@@ -108,6 +109,11 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
 				state = WaitingForCredentials;
 				onNeedCredentials();
 			}
+			else if ((stream->isTLSEncrypted() || allowPLAINOverNonTLS) && streamFeatures->hasAuthenticationMechanism("PLAIN")) {
+				authenticator = new PLAINClientAuthenticator();
+				state = WaitingForCredentials;
+				onNeedCredentials();
+			}
 			else if (streamFeatures->hasAuthenticationMechanism("DIGEST-MD5")) {
 				std::ostringstream s;
 				s << boost::uuids::random_generator()();
@@ -116,11 +122,6 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
 				state = WaitingForCredentials;
 				onNeedCredentials();
 			}
-			else if (streamFeatures->hasAuthenticationMechanism("PLAIN")) {
-				authenticator = new PLAINClientAuthenticator();
-				state = WaitingForCredentials;
-				onNeedCredentials();
-			}
 			else {
 				finishSession(Error::NoSupportedAuthMechanismsError);
 			}
diff --git a/Swiften/Client/ClientSession.h b/Swiften/Client/ClientSession.h
index fa52706..37f8bea 100644
--- a/Swiften/Client/ClientSession.h
+++ b/Swiften/Client/ClientSession.h
@@ -61,6 +61,10 @@ namespace Swift {
 				return state;
 			}
 
+			void setAllowPLAINOverNonTLS(bool b) {
+				allowPLAINOverNonTLS = b;
+			}
+
 			void start();
 			void finish();
 
@@ -100,6 +104,7 @@ namespace Swift {
 			JID localJID;
 			State state;
 			boost::shared_ptr<SessionStream> stream;
+			bool allowPLAINOverNonTLS;
 			bool needSessionStart;
 			ClientAuthenticator* authenticator;
 	};
diff --git a/Swiften/Client/UnitTest/ClientSessionTest.cpp b/Swiften/Client/UnitTest/ClientSessionTest.cpp
index 8e0a85d..180eab8 100644
--- a/Swiften/Client/UnitTest/ClientSessionTest.cpp
+++ b/Swiften/Client/UnitTest/ClientSessionTest.cpp
@@ -138,6 +138,19 @@ class ClientSessionTest : public CppUnit::TestFixture {
 			CPPUNIT_ASSERT(sessionFinishedError);
 		}
 
+		void testAuthenticate_PLAINOverNonTLS() {
+			boost::shared_ptr<ClientSession> session(createSession());
+			session->setAllowPLAINOverNonTLS(false);
+			session->start();
+			server->receiveStreamStart();
+			server->sendStreamStart();
+			server->sendStreamFeaturesWithPLAINAuthentication();
+
+			CPPUNIT_ASSERT_EQUAL(ClientSession::Finished, session->getState());
+			CPPUNIT_ASSERT(sessionFinishedReceived);
+			CPPUNIT_ASSERT(sessionFinishedError);
+		}
+
 		void testAuthenticate_NoValidAuthMechanisms() {
 			boost::shared_ptr<ClientSession> session(createSession());
 			session->start();
@@ -155,6 +168,7 @@ class ClientSessionTest : public CppUnit::TestFixture {
 			boost::shared_ptr<ClientSession> session = ClientSession::create(JID("me@foo.com"), server);
 			session->onFinished.connect(boost::bind(&ClientSessionTest::handleSessionFinished, this, _1));
 			session->onNeedCredentials.connect(boost::bind(&ClientSessionTest::handleSessionNeedCredentials, this));
+			session->setAllowPLAINOverNonTLS(true);
 			return session;
 		}
 
@@ -206,6 +220,10 @@ class ClientSessionTest : public CppUnit::TestFixture {
 					tlsEncrypted = true;
 				}
 
+				virtual bool isTLSEncrypted() {
+					return tlsEncrypted;
+				}
+
 				virtual void addZLibCompression() {
 					compressed = true;
 				}
diff --git a/Swiften/Session/BasicSessionStream.cpp b/Swiften/Session/BasicSessionStream.cpp
index 861b9d0..d75e2c3 100644
--- a/Swiften/Session/BasicSessionStream.cpp
+++ b/Swiften/Session/BasicSessionStream.cpp
@@ -81,6 +81,10 @@ void BasicSessionStream::addTLSEncryption() {
 	}
 }
 
+bool BasicSessionStream::isTLSEncrypted() {
+	return tlsLayer;
+}
+
 void BasicSessionStream::addZLibCompression() {
 	boost::shared_ptr<CompressionLayer> compressionLayer(new CompressionLayer());
 	streamStack->addLayer(compressionLayer);
diff --git a/Swiften/Session/BasicSessionStream.h b/Swiften/Session/BasicSessionStream.h
index 7c98992..7f194ff 100644
--- a/Swiften/Session/BasicSessionStream.h
+++ b/Swiften/Session/BasicSessionStream.h
@@ -49,6 +49,7 @@ namespace Swift {
 
 			virtual bool supportsTLSEncryption();
 			virtual void addTLSEncryption();
+			virtual bool isTLSEncrypted();
 
 			virtual void setWhitespacePingEnabled(bool);
 
diff --git a/Swiften/Session/SessionStream.h b/Swiften/Session/SessionStream.h
index 614d237..f2d4a7b 100644
--- a/Swiften/Session/SessionStream.h
+++ b/Swiften/Session/SessionStream.h
@@ -44,6 +44,7 @@ namespace Swift {
 
 			virtual bool supportsTLSEncryption() = 0;
 			virtual void addTLSEncryption() = 0;
+			virtual bool isTLSEncrypted() = 0;
 			virtual void setWhitespacePingEnabled(bool enabled) = 0;
 
 			virtual void resetXMPPParser() = 0;
-- 
cgit v0.10.2-6-g49f6