From 08536b4ed31c30a25a343c3c2619676e67a0c692 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Tue, 12 Jul 2011 20:43:33 +0200
Subject: Fixed bug with illegal resource in JID resulting in empty resource.


diff --git a/Swiften/IDN/StringPrep.cpp b/Swiften/IDN/StringPrep.cpp
index ff01eed..d54fb0b 100644
--- a/Swiften/IDN/StringPrep.cpp
+++ b/Swiften/IDN/StringPrep.cpp
@@ -26,14 +26,13 @@ const Stringprep_profile* getLibIDNProfile(StringPrep::Profile profile) {
 }
 
 std::string StringPrep::getPrepared(const std::string& s, Profile profile) {
-	
 	std::vector<char> input(s.begin(), s.end());
 	input.resize(MAX_STRINGPREP_SIZE);
 	if (stringprep(&input[0], MAX_STRINGPREP_SIZE, static_cast<Stringprep_profile_flags>(0), getLibIDNProfile(profile)) == 0) {
 		return std::string(&input[0]);
 	}
 	else {
-		return "";
+		throw std::exception();
 	}
 }
 
diff --git a/Swiften/JID/JID.cpp b/Swiften/JID/JID.cpp
index e4611b3..925c763 100644
--- a/Swiften/JID/JID.cpp
+++ b/Swiften/JID/JID.cpp
@@ -29,24 +29,25 @@ static PrepCache resourcePrepCache;
 
 namespace Swift {
 
-JID::JID(const char* jid) {
+JID::JID(const char* jid) : valid_(true) {
 	initializeFromString(std::string(jid));
 }
 
-JID::JID(const std::string& jid) {
+JID::JID(const std::string& jid) : valid_(true) {
 	initializeFromString(jid);
 }
 
-JID::JID(const std::string& node, const std::string& domain) : hasResource_(false) {
+JID::JID(const std::string& node, const std::string& domain) : valid_(true), hasResource_(false) {
 	nameprepAndSetComponents(node, domain, "");
 }
 
-JID::JID(const std::string& node, const std::string& domain, const std::string& resource) : hasResource_(true) {
+JID::JID(const std::string& node, const std::string& domain, const std::string& resource) : valid_(true), hasResource_(true) {
 	nameprepAndSetComponents(node, domain, resource);
 }
 
 void JID::initializeFromString(const std::string& jid) {
 	if (String::beginsWith(jid, '@')) {
+		valid_ = false;
 		return;
 	}
 
@@ -72,31 +73,40 @@ void JID::initializeFromString(const std::string& jid) {
 
 
 void JID::nameprepAndSetComponents(const std::string& node, const std::string& domain, const std::string& resource) {
+	try {
 #ifndef SWIFTEN_CACHE_JID_PREP
-	node_ = StringPrep::getPrepared(node, StringPrep::NamePrep);
-	domain_ = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep);
-	resource_ = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep);
+		node_ = StringPrep::getPrepared(node, StringPrep::NamePrep);
+		domain_ = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep);
+		resource_ = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep);
 #else
-	std::pair<PrepCache::iterator, bool> r;
+		std::pair<PrepCache::iterator, bool> r;
 
-	r = nodePrepCache.insert(std::make_pair(node, std::string()));
-	if (r.second) {
-		r.first->second = StringPrep::getPrepared(node, StringPrep::NamePrep);
-	}
-	node_ = r.first->second;
+		r = nodePrepCache.insert(std::make_pair(node, std::string()));
+		if (r.second) {
+			r.first->second = StringPrep::getPrepared(node, StringPrep::NamePrep);
+		}
+		node_ = r.first->second;
 
-	r = domainPrepCache.insert(std::make_pair(domain, std::string()));
-	if (r.second) {
-		r.first->second = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep);
-	}
-	domain_ = r.first->second;
+		r = domainPrepCache.insert(std::make_pair(domain, std::string()));
+		if (r.second) {
+			r.first->second = StringPrep::getPrepared(domain, StringPrep::XMPPNodePrep);
+		}
+		domain_ = r.first->second;
+		if (domain_.empty()) {
+			valid_ = false;
+			return;
+		}
 
-	r = resourcePrepCache.insert(std::make_pair(resource, std::string()));
-	if (r.second) {
-		r.first->second = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep);
-	}
-	resource_ = r.first->second;
+		r = resourcePrepCache.insert(std::make_pair(resource, std::string()));
+		if (r.second) {
+			r.first->second = StringPrep::getPrepared(resource, StringPrep::XMPPResourcePrep);
+		}
+		resource_ = r.first->second;
 #endif
+	}
+	catch (const std::exception&) {
+		valid_ = false;
+	}
 }
 
 std::string JID::toString() const {
diff --git a/Swiften/JID/JID.h b/Swiften/JID/JID.h
index 63e063d..1a7dbe3 100644
--- a/Swiften/JID/JID.h
+++ b/Swiften/JID/JID.h
@@ -22,7 +22,7 @@ namespace Swift {
 			JID(const std::string& node, const std::string& domain, const std::string& resource);
 
 			bool isValid() const {
-				return !domain_.empty(); /* FIXME */
+				return valid_;
 			}
 
 			const std::string& getNode() const {
@@ -79,6 +79,7 @@ namespace Swift {
 			void initializeFromString(const std::string&);
 	
 		private:
+			bool valid_;
 			std::string node_;
 			std::string domain_;
 			bool hasResource_;
diff --git a/Swiften/JID/UnitTest/JIDTest.cpp b/Swiften/JID/UnitTest/JIDTest.cpp
index 0f22e15..f406635 100644
--- a/Swiften/JID/UnitTest/JIDTest.cpp
+++ b/Swiften/JID/UnitTest/JIDTest.cpp
@@ -23,6 +23,7 @@ class JIDTest : public CppUnit::TestFixture
 		CPPUNIT_TEST(testConstructorWithString_UpperCaseDomain);
 		CPPUNIT_TEST(testConstructorWithString_UpperCaseResource);
 		CPPUNIT_TEST(testConstructorWithString_EmptyNode);
+		CPPUNIT_TEST(testConstructorWithString_IllegalResource);
 		CPPUNIT_TEST(testConstructorWithStrings);
 		CPPUNIT_TEST(testIsBare);
 		CPPUNIT_TEST(testIsBare_NotBare);
@@ -124,6 +125,12 @@ class JIDTest : public CppUnit::TestFixture
 			CPPUNIT_ASSERT(!testling.isValid());
 		}
 
+		void testConstructorWithString_IllegalResource() {
+			JID testling("foo@bar.com/\xd8\xb1\xd9\x85\xd9\x82\xd9\x87\x20\xd8\xaa\xd8\xb1\xd9\x86\xd8\xb3\x20");
+
+			CPPUNIT_ASSERT(!testling.isValid());
+		}
+
 		void testConstructorWithStrings() {
 			JID testling("foo", "bar", "baz");
 
diff --git a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
index 2dd7bf4..33de014 100644
--- a/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
+++ b/Swiften/SASL/SCRAMSHA1ClientAuthenticator.cpp
@@ -99,7 +99,11 @@ bool SCRAMSHA1ClientAuthenticator::setChallenge(const boost::optional<ByteArray>
 		}
 
 		// Compute all the values needed for the server signature
-		saltedPassword = PBKDF2::encode(StringPrep::getPrepared(getPassword(), StringPrep::SASLPrep), salt, iterations);
+		try {
+			saltedPassword = PBKDF2::encode(StringPrep::getPrepared(getPassword(), StringPrep::SASLPrep), salt, iterations);
+		}
+		catch (const std::exception&) {
+		}
 		authMessage = getInitialBareClientMessage() + "," + initialServerMessage + "," + getFinalMessageWithoutProof();
 		ByteArray serverKey = HMACSHA1::getResult(saltedPassword, "Server Key");
 		serverSignature = HMACSHA1::getResult(serverKey, authMessage);
@@ -146,7 +150,12 @@ std::map<char, std::string> SCRAMSHA1ClientAuthenticator::parseMap(const std::st
 }
 
 ByteArray SCRAMSHA1ClientAuthenticator::getInitialBareClientMessage() const {
-	std::string authenticationID = StringPrep::getPrepared(getAuthenticationID(), StringPrep::SASLPrep);
+	std::string authenticationID;
+	try {
+	 authenticationID = StringPrep::getPrepared(getAuthenticationID(), StringPrep::SASLPrep);
+	}
+	catch (const std::exception&) {
+	}
 	return ByteArray(std::string("n=" + escape(authenticationID) + ",r=" + clientnonce));
 }
 
-- 
cgit v0.10.2-6-g49f6