summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslsocket.cpp
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-03-28 09:23:03 +0200
committerLiang Qi <liang.qi@qt.io>2017-03-28 09:28:31 +0200
commitb48a13fd6843e12b5725aa3ff0d010007e7c43b4 (patch)
tree316cfe36fc67906efcd92ff806c7c0da56ed4f8e /src/network/ssl/qsslsocket.cpp
parent3398d9d40cb0dae2dc2a1a4f7dc3b4b9cceae903 (diff)
parent15fe60cfdada84ea519f08e905d59cc3fb6d20cd (diff)
Merge remote-tracking branch 'origin/5.9' into dev
Conflicts: examples/examples.pro tests/auto/corelib/tools/qchar/tst_qchar.cpp tests/auto/other/qaccessibility/accessiblewidgets.h Change-Id: I426696c40ab57d14dc295b8103152cede79f244c
Diffstat (limited to 'src/network/ssl/qsslsocket.cpp')
-rw-r--r--src/network/ssl/qsslsocket.cpp25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index b4109cadb5..84b8f3a8d9 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>
@@ -2679,31 +2680,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);
@@ -2720,13 +2725,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);