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;