Blob Blame History Raw
Patch for CVE-2014-350.  Inspired by Debian's patch:
https://sources.debian.net/src/poco/1.3.6p1-5.1/debian/patches/70_fix_CVE-2014-0350.dpatch/
https://github.com/pocoproject/poco/issues/615

diff -up poco-1.4.2p1-all/NetSSL_OpenSSL/src/X509Certificate.cpp.CVE-2014-0350 poco-1.4.2p1-all/NetSSL_OpenSSL/src/X509Certificate.cpp
--- poco-1.4.2p1-all/NetSSL_OpenSSL/src/X509Certificate.cpp.CVE-2014-0350	2011-09-24 04:07:03.000000000 -0400
+++ poco-1.4.2p1-all/NetSSL_OpenSSL/src/X509Certificate.cpp	2016-02-08 20:39:15.392230633 -0500
@@ -48,6 +48,21 @@
 #include <openssl/x509v3.h>
 #include <openssl/err.h>
 
+static bool matchWildcard(const std::string& wildcard, const std::string& hostName)
+{
+	// fix wildcards
+	std::string wildcardExpr("^");
+	wildcardExpr += Poco::replace(wildcard, ".", "\\.");
+	Poco::replaceInPlace(wildcardExpr, "*", ".*");
+	Poco::replaceInPlace(wildcardExpr, "..*", ".*");
+	Poco::replaceInPlace(wildcardExpr, "?", ".?");
+	Poco::replaceInPlace(wildcardExpr, "..?", ".?");
+	wildcardExpr += "$";
+
+	Poco::RegularExpression expr(wildcardExpr, Poco::RegularExpression::RE_CASELESS);
+	return expr.match(hostName);
+}
+
 
 namespace Poco {
 namespace Net {
@@ -107,51 +122,46 @@ bool X509Certificate::verify(const Poco:
 	std::string commonName;
 	std::set<std::string> dnsNames;
 	certificate.extractNames(commonName, dnsNames);
+	if (!commonName.empty()) dnsNames.insert(commonName);
 	bool ok = (dnsNames.find(hostName) != dnsNames.end());
-
-	char buffer[NAME_BUFFER_SIZE];
-	X509_NAME* subj = 0;
-	if (!ok && (subj = X509_get_subject_name(const_cast<X509*>(certificate.certificate()))) && X509_NAME_get_text_by_NID(subj, NID_commonName, buffer, sizeof(buffer)) > 0)
+	if (!ok)
 	{
-		buffer[NAME_BUFFER_SIZE - 1] = 0;
-		std::string commonName(buffer); // commonName can contain wildcards like *.appinf.com
-		try
+		for (std::set<std::string>::const_iterator it = dnsNames.begin(); !ok && it != dnsNames.end(); ++it)
 		{
-			// two cases: strData contains wildcards or not
-			if (containsWildcards(commonName))
+			try
 			{
-				// a compare by IPAddress is not possible with wildcards
-				// only allow compare by name
-				const HostEntry& heData = DNS::resolve(hostName);
-				ok = matchByAlias(commonName, heData);
-			}
-			else
-			{
-				// it depends on hostName if we compare by IP or by alias
-				IPAddress ip;
-				if (IPAddress::tryParse(hostName, ip))
+				// two cases: strData contains wildcards or not
+				if (containsWildcards(*it))
 				{
-					// compare by IP
-					const HostEntry& heData = DNS::resolve(commonName);
-					const HostEntry::AddressList& addr = heData.addresses();
-					HostEntry::AddressList::const_iterator it = addr.begin();
-					HostEntry::AddressList::const_iterator itEnd = addr.end();
-					for (; it != itEnd && !ok; ++it)
-					{
-						ok = (*it == ip);
-					}
+					// a compare by IPAddress is not possible with wildcards
+					// only allow compare by name
+					ok = matchWildcard(*it, hostName);
 				}
 				else
 				{
-					// compare by name
-					const HostEntry& heData = DNS::resolve(hostName);
-					ok = matchByAlias(commonName, heData);
+					// it depends on hostName if we compare by IP or by alias
+					IPAddress ip;
+					if (IPAddress::tryParse(hostName, ip))
+					{
+						// compare by IP
+						const HostEntry& heData = DNS::resolve(*it);
+						const HostEntry::AddressList& addr = heData.addresses();
+						HostEntry::AddressList::const_iterator it = addr.begin();
+						HostEntry::AddressList::const_iterator itEnd = addr.end();
+						for (; it != itEnd && !ok; ++it)
+						{
+							ok = (*it == ip);
+						}
+					}
+					else
+					{
+						ok = Poco::icompare(*it, hostName) == 0;
+					}
 				}
 			}
-		}
-		catch (HostNotFoundException&)
-		{
-			return false;
+			catch (HostNotFoundException&)
+			{
+			}
 		}
 	}
 	return ok;