summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-03-27 10:42:08 +0200
committerLiang Qi <liang.qi@qt.io>2017-03-27 10:42:08 +0200
commit7702fe86029c771e641a918baa221b9737c0f18e (patch)
tree8e0795bc4c701518e1c66922f8e8b0cb359da155 /src/network
parent1dd54b5647d33416c39fb41fdab560c815356951 (diff)
parent38550c562d918e783bb609622bc8fb46de1bfec4 (diff)
Merge remote-tracking branch 'origin/5.8' into 5.9
Diffstat (limited to 'src/network')
-rw-r--r--src/network/ssl/qsslsocket.cpp25
-rw-r--r--src/network/ssl/qsslsocket_p.h3
2 files changed, 21 insertions, 7 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index bb0d949684..e655f4becd 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -326,6 +326,7 @@
#include <QtCore/qdebug.h>
#include <QtCore/qdir.h>
#include <QtCore/qmutex.h>
+#include <QtCore/qurl.h>
#include <QtCore/qelapsedtimer.h>
#include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qhostinfo.h>
@@ -2672,31 +2673,35 @@ QSharedPointer<QSslContext> QSslSocketPrivate::sslContext(QSslSocket *socket)
bool QSslSocketPrivate::isMatchingHostname(const QSslCertificate &cert, const QString &peerName)
{
- const QString lowerPeerName = peerName.toLower();
+ const QString lowerPeerName = QString::fromLatin1(QUrl::toAce(peerName));
const QStringList commonNames = cert.subjectInfo(QSslCertificate::CommonName);
for (const QString &commonName : commonNames) {
- if (isMatchingHostname(commonName.toLower(), lowerPeerName))
+ if (isMatchingHostname(commonName, lowerPeerName))
return true;
}
const auto subjectAlternativeNames = cert.subjectAlternativeNames();
const auto altNames = subjectAlternativeNames.equal_range(QSsl::DnsEntry);
for (auto it = altNames.first; it != altNames.second; ++it) {
- if (isMatchingHostname(it->toLower(), lowerPeerName))
+ if (isMatchingHostname(*it, lowerPeerName))
return true;
}
return false;
}
+/*! \internal
+ Checks if the certificate's name \a cn matches the \a hostname.
+ \a hostname must be normalized in ASCII-Compatible Encoding, but \a cn is not normalized
+ */
bool QSslSocketPrivate::isMatchingHostname(const QString &cn, const QString &hostname)
{
int wildcard = cn.indexOf(QLatin1Char('*'));
// Check this is a wildcard cert, if not then just compare the strings
if (wildcard < 0)
- return cn == hostname;
+ return QLatin1String(QUrl::toAce(cn)) == hostname;
int firstCnDot = cn.indexOf(QLatin1Char('.'));
int secondCnDot = cn.indexOf(QLatin1Char('.'), firstCnDot+1);
@@ -2713,13 +2718,21 @@ bool QSslSocketPrivate::isMatchingHostname(const QString &cn, const QString &hos
if (cn.lastIndexOf(QLatin1Char('*')) != wildcard)
return false;
+ // Reject wildcard character embedded within the A-labels or U-labels of an internationalized
+ // domain name (RFC6125 section 7.2)
+ if (cn.startsWith(QLatin1String("xn--"), Qt::CaseInsensitive))
+ return false;
+
// Check characters preceding * (if any) match
- if (wildcard && (hostname.leftRef(wildcard) != cn.leftRef(wildcard)))
+ if (wildcard && hostname.leftRef(wildcard).compare(cn.leftRef(wildcard), Qt::CaseInsensitive) != 0)
return false;
// Check characters following first . match
- if (hostname.midRef(hostname.indexOf(QLatin1Char('.'))) != cn.midRef(firstCnDot))
+ int hnDot = hostname.indexOf(QLatin1Char('.'));
+ if (hostname.midRef(hnDot + 1) != cn.midRef(firstCnDot + 1)
+ && hostname.midRef(hnDot + 1) != QLatin1String(QUrl::toAce(cn.mid(firstCnDot + 1)))) {
return false;
+ }
// Check if the hostname is an IP address, if so then wildcards are not allowed
QHostAddress addr(hostname);
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index cec61d07c1..aec3437422 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -151,7 +151,8 @@ public:
QRegExp::PatternSyntax syntax);
static void addDefaultCaCertificate(const QSslCertificate &cert);
static void addDefaultCaCertificates(const QList<QSslCertificate> &certs);
- static bool isMatchingHostname(const QSslCertificate &cert, const QString &peerName);
+ Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QSslCertificate &cert,
+ const QString &peerName);
Q_AUTOTEST_EXPORT static bool isMatchingHostname(const QString &cn, const QString &hostname);
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)