From dd2d1fbbce68afda9b9857a84564924f05935c4a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Thu, 3 Jun 2010 22:11:32 +0200
Subject: Use SASL EXTERNAL for authenticating in Slimber.


diff --git a/Slimber/Server.cpp b/Slimber/Server.cpp
index cbb52b7..5b08d93 100644
--- a/Slimber/Server.cpp
+++ b/Slimber/Server.cpp
@@ -144,6 +144,7 @@ void Server::handleNewClientConnection(boost::shared_ptr<Connection> connection)
 	serverFromClientSession = boost::shared_ptr<ServerFromClientSession>(
 			new ServerFromClientSession(idGenerator.generateID(), connection, 
 					&payloadParserFactories, &payloadSerializers, &userRegistry));
+	serverFromClientSession->setAllowSASLEXTERNAL();
 	serverFromClientSession->onSessionStarted.connect(
 			boost::bind(&Server::handleSessionStarted, this));
 	serverFromClientSession->onElementReceived.connect(
diff --git a/Swiften/Client/ClientSession.cpp b/Swiften/Client/ClientSession.cpp
index 5e2cd84..88b3d5a 100644
--- a/Swiften/Client/ClientSession.cpp
+++ b/Swiften/Client/ClientSession.cpp
@@ -101,6 +101,10 @@ void ClientSession::handleElement(boost::shared_ptr<Element> element) {
 					finishSession(Error::TLSClientCertificateError);
 				}
 			}
+			else if (streamFeatures->hasAuthenticationMechanism("EXTERNAL")) {
+				state = Authenticating;
+				stream->writeElement(boost::shared_ptr<Element>(new AuthRequest("EXTERNAL", "")));
+			}
 			else if (streamFeatures->hasAuthenticationMechanism("SCRAM-SHA-1")) {
 				// FIXME: Use a real nonce
 				std::ostringstream s;
diff --git a/Swiften/Server/ServerFromClientSession.cpp b/Swiften/Server/ServerFromClientSession.cpp
index 882946d..e63b9e2 100644
--- a/Swiften/Server/ServerFromClientSession.cpp
+++ b/Swiften/Server/ServerFromClientSession.cpp
@@ -43,23 +43,30 @@ void ServerFromClientSession::handleElement(boost::shared_ptr<Element> element)
 	}
 	else {
 		if (AuthRequest* authRequest = dynamic_cast<AuthRequest*>(element.get())) {
-			if (authRequest->getMechanism() != "PLAIN") {
-				getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
-				finishSession(NoSupportedAuthMechanismsError);
-			}
-			else {
-				PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : "");
-				if (userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), plainMessage.getPassword())) {
-					getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
-					user_ = plainMessage.getAuthenticationID();
-					authenticated_ = true;
-					getXMPPLayer()->resetParser();
+			if (authRequest->getMechanism() == "PLAIN" || (allowSASLEXTERNAL && authRequest->getMechanism() == "EXTERNAL")) {
+				if (authRequest->getMechanism() == "EXTERNAL") {
+						getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
+						authenticated_ = true;
+						getXMPPLayer()->resetParser();
 				}
 				else {
-					getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
-					finishSession(AuthenticationFailedError);
+					PLAINMessage plainMessage(authRequest->getMessage() ? *authRequest->getMessage() : "");
+					if (userRegistry_->isValidUserPassword(JID(plainMessage.getAuthenticationID(), getLocalJID().getDomain()), plainMessage.getPassword())) {
+						getXMPPLayer()->writeElement(boost::shared_ptr<AuthSuccess>(new AuthSuccess()));
+						user_ = plainMessage.getAuthenticationID();
+						authenticated_ = true;
+						getXMPPLayer()->resetParser();
+					}
+					else {
+						getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
+						finishSession(AuthenticationFailedError);
+					}
 				}
 			}
+			else {
+				getXMPPLayer()->writeElement(boost::shared_ptr<AuthFailure>(new AuthFailure));
+				finishSession(NoSupportedAuthMechanismsError);
+			}
 		}
 		else if (IQ* iq = dynamic_cast<IQ*>(element.get())) {
 			if (boost::shared_ptr<ResourceBind> resourceBind = iq->getPayload<ResourceBind>()) {
@@ -86,6 +93,9 @@ void ServerFromClientSession::handleStreamStart(const ProtocolHeader& incomingHe
 	boost::shared_ptr<StreamFeatures> features(new StreamFeatures());
 	if (!authenticated_) {
 		features->addAuthenticationMechanism("PLAIN");
+		if (allowSASLEXTERNAL) {
+			features->addAuthenticationMechanism("EXTERNAL");
+		}
 	}
 	else {
 		features->setHasResourceBind();
@@ -99,5 +109,8 @@ void ServerFromClientSession::setInitialized() {
 	onSessionStarted();
 }
 
+void ServerFromClientSession::setAllowSASLEXTERNAL() {
+	allowSASLEXTERNAL = true;
+}
 
 }
diff --git a/Swiften/Server/ServerFromClientSession.h b/Swiften/Server/ServerFromClientSession.h
index 5883742..2ac4296 100644
--- a/Swiften/Server/ServerFromClientSession.h
+++ b/Swiften/Server/ServerFromClientSession.h
@@ -38,6 +38,7 @@ namespace Swift {
 					UserRegistry* userRegistry);
 
 			boost::signal<void ()> onSessionStarted;
+			void setAllowSASLEXTERNAL();
 
 		private:
 			void handleElement(boost::shared_ptr<Element>);
@@ -53,6 +54,7 @@ namespace Swift {
 			UserRegistry* userRegistry_;
 			bool authenticated_;
 			bool initialized;
+			bool allowSASLEXTERNAL;
 			String user_;
 	};
 }
-- 
cgit v0.10.2-6-g49f6