1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-01-31 18:07:14 +01:00
SqMod/vendor/POCO/NetSSL_OpenSSL/src/X509Certificate.cpp
Sandu Liviu Catalin 4a6bfc086c Major plugin refactor and cleanup.
Switched to POCO library for unified platform/library interface.
Deprecated the external module API. It was creating more problems than solving.
Removed most built-in libraries in favor of system libraries for easier maintenance.
Cleaned and secured code with help from static analyzers.
2021-01-30 08:51:39 +02:00

203 lines
4.4 KiB
C++

//
// X509Certificate.cpp
//
// Library: NetSSL_OpenSSL
// Package: SSLCore
// Module: X509Certificate
//
// Copyright (c) 2006-2009, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
// SPDX-License-Identifier: BSL-1.0
//
#include "Poco/Net/X509Certificate.h"
#include "Poco/Net/SSLException.h"
#include "Poco/Net/SSLManager.h"
#include "Poco/Net/DNS.h"
#include "Poco/TemporaryFile.h"
#include "Poco/FileStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/String.h"
#include "Poco/RegularExpression.h"
#include "Poco/DateTimeParser.h"
#include <openssl/pem.h>
#include <openssl/x509v3.h>
#include <openssl/err.h>
namespace Poco {
namespace Net {
X509Certificate::X509Certificate(std::istream& istr):
Poco::Crypto::X509Certificate(istr)
{
}
X509Certificate::X509Certificate(const std::string& path):
Poco::Crypto::X509Certificate(path)
{
}
X509Certificate::X509Certificate(X509* pCert):
Poco::Crypto::X509Certificate(pCert)
{
}
X509Certificate::X509Certificate(X509* pCert, bool shared):
Poco::Crypto::X509Certificate(pCert, shared)
{
}
X509Certificate::X509Certificate(const Poco::Crypto::X509Certificate& cert):
Poco::Crypto::X509Certificate(cert)
{
}
X509Certificate::X509Certificate(const X509Certificate& cert):
Poco::Crypto::X509Certificate(cert)
{
}
X509Certificate::X509Certificate(X509Certificate&& cert) noexcept:
Poco::Crypto::X509Certificate(std::move(cert))
{
}
X509Certificate& X509Certificate::operator = (const Poco::Crypto::X509Certificate& cert)
{
X509Certificate tmp(cert);
swap(tmp);
return *this;
}
X509Certificate& X509Certificate::operator = (const X509Certificate& cert)
{
X509Certificate tmp(cert);
swap(tmp);
return *this;
}
X509Certificate& X509Certificate::operator = (X509Certificate&& cert) noexcept
{
Poco::Crypto::X509Certificate::operator = (std::move(cert));
return *this;
}
X509Certificate::~X509Certificate()
{
}
bool X509Certificate::verify(const std::string& hostName) const
{
return verify(*this, hostName);
}
bool X509Certificate::verify(const Poco::Crypto::X509Certificate& certificate, const std::string& hostName)
{
#if OPENSSL_VERSION_NUMBER < 0x10002000L
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());
if (!ok)
{
for (std::set<std::string>::const_iterator it = dnsNames.begin(); !ok && it != dnsNames.end(); ++it)
{
try
{
// two cases: name contains wildcards or not
if (containsWildcards(*it))
{
// a compare by IPAddress is not possible with wildcards
// only allow compare by name
ok = matchWildcard(*it, hostName);
}
else
{
// it depends on hostName whether 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 (NoAddressFoundException&)
{
}
catch (HostNotFoundException&)
{
}
}
}
return ok;
#else
if (X509_check_host(const_cast<X509*>(certificate.certificate()), hostName.c_str(), hostName.length(), 0, NULL) == 1)
{
return true;
}
else
{
IPAddress ip;
if (IPAddress::tryParse(hostName, ip))
{
return (X509_check_ip_asc(const_cast<X509*>(certificate.certificate()), hostName.c_str(), 0) == 1);
}
}
return false;
#endif
}
bool X509Certificate::containsWildcards(const std::string& commonName)
{
return (commonName.find('*') != std::string::npos || commonName.find('?') != std::string::npos);
}
bool X509Certificate::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::Net