diff options
Diffstat (limited to 'Swiften/TLS/ServerIdentityVerifier.cpp')
-rw-r--r-- | Swiften/TLS/ServerIdentityVerifier.cpp | 128 |
1 files changed, 68 insertions, 60 deletions
diff --git a/Swiften/TLS/ServerIdentityVerifier.cpp b/Swiften/TLS/ServerIdentityVerifier.cpp index 02459b9..18ea2aa 100644 --- a/Swiften/TLS/ServerIdentityVerifier.cpp +++ b/Swiften/TLS/ServerIdentityVerifier.cpp @@ -1,88 +1,96 @@ /* - * Copyright (c) 2010 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #include <Swiften/TLS/ServerIdentityVerifier.h> #include <boost/algorithm/string.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/IDN/IDNConverter.h> namespace Swift { -ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter) { - domain = jid.getDomain(); - encodedDomain = idnConverter->getIDNAEncoded(domain); +ServerIdentityVerifier::ServerIdentityVerifier(const JID& jid, IDNConverter* idnConverter, bool checkServer) : domainValid(false), checkServer_(checkServer) { + domain = jid.getDomain(); + boost::optional<std::string> domainResult = idnConverter->getIDNAEncoded(domain); + if (!!domainResult) { + encodedDomain = *domainResult; + domainValid = true; + } } bool ServerIdentityVerifier::certificateVerifies(Certificate::ref certificate) { - bool hasSAN = false; + bool hasSAN = false; - if (certificate == NULL) { - return false; - } - // DNS names - std::vector<std::string> dnsNames = certificate->getDNSNames(); - foreach (const std::string& dnsName, dnsNames) { - if (matchesDomain(dnsName)) { - return true; - } - } - hasSAN |= !dnsNames.empty(); + if (certificate == nullptr) { + return false; + } + // DNS names + std::vector<std::string> dnsNames = certificate->getDNSNames(); + for (const auto& dnsName : dnsNames) { + if (matchesDomain(dnsName)) { + return true; + } + } + hasSAN |= !dnsNames.empty(); - // SRV names - std::vector<std::string> srvNames = certificate->getSRVNames(); - foreach (const std::string& srvName, srvNames) { - // Only match SRV names that begin with the service; this isn't required per - // spec, but we're being purist about this. - if (boost::starts_with(srvName, "_xmpp-client.") && matchesDomain(srvName.substr(std::string("_xmpp-client.").size(), srvName.npos))) { - return true; - } - } - hasSAN |= !srvNames.empty(); + std::string prefix = (checkServer_) ? "_xmpp-server." : "_xmpp-client."; - // XmppAddr - std::vector<std::string> xmppAddresses = certificate->getXMPPAddresses(); - foreach (const std::string& xmppAddress, xmppAddresses) { - if (matchesAddress(xmppAddress)) { - return true; - } - } - hasSAN |= !xmppAddresses.empty(); + // SRV names + std::vector<std::string> srvNames = certificate->getSRVNames(); + for (const auto& srvName : srvNames) { + // Only match SRV names that begin with the service; this isn't required per + // spec, but we're being purist about this. + if (boost::starts_with(srvName, prefix) && matchesDomain(srvName.substr(prefix.size(), srvName.npos))) { + return true; + } + } + hasSAN |= !srvNames.empty(); - // CommonNames. Only check this if there was no SAN (according to spec). - if (!hasSAN) { - std::vector<std::string> commonNames = certificate->getCommonNames(); - foreach (const std::string& commonName, commonNames) { - if (matchesDomain(commonName)) { - return true; - } - } - } + // XmppAddr + std::vector<std::string> xmppAddresses = certificate->getXMPPAddresses(); + for (const auto& xmppAddress : xmppAddresses) { + if (matchesAddress(xmppAddress)) { + return true; + } + } + hasSAN |= !xmppAddresses.empty(); - return false; + // CommonNames. Only check this if there was no SAN (according to spec). + if (!hasSAN) { + std::vector<std::string> commonNames = certificate->getCommonNames(); + for (const auto& commonName : commonNames) { + if (matchesDomain(commonName)) { + return true; + } + } + } + + return false; } bool ServerIdentityVerifier::matchesDomain(const std::string& s) const { - if (boost::starts_with(s, "*.")) { - std::string matchString(s.substr(2, s.npos)); - std::string matchDomain = encodedDomain; - size_t dotIndex = matchDomain.find('.'); - if (dotIndex != matchDomain.npos) { - matchDomain = matchDomain.substr(dotIndex + 1, matchDomain.npos); - } - return matchString == matchDomain; - } - else { - return s == encodedDomain; - } + if (!domainValid) { + return false; + } + if (boost::starts_with(s, "*.")) { + std::string matchString(s.substr(2, s.npos)); + std::string matchDomain = encodedDomain; + size_t dotIndex = matchDomain.find('.'); + if (dotIndex != matchDomain.npos) { + matchDomain = matchDomain.substr(dotIndex + 1, matchDomain.npos); + } + return boost::iequals(matchString, matchDomain); + } + else { + return boost::iequals(s, encodedDomain); + } } bool ServerIdentityVerifier::matchesAddress(const std::string& s) const { - return s == domain; + return boost::iequals(s, domain); } } |