Index: kio/kio/tcpslavebase.cpp =================================================================== --- kio/kio/tcpslavebase.cpp (revision 1173815) +++ kio/kio/tcpslavebase.cpp (working copy) @@ -4,6 +4,7 @@ * Copyright (C) 2001 Dawit Alemayehu * Copyright (C) 2007,2008 Andreas Hartmetz * Copyright (C) 2008 Roland Harnau + * Copyright (C) 2010 Richard Moore * * This file is part of the KDE project * @@ -452,7 +453,46 @@ return startTLSInternal(KTcpSocket::TlsV1) & ResultOk; } +bool TCPSlaveBase::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; + + int firstCnDot = cn.indexOf(QLatin1Char('.')); + int secondCnDot = cn.indexOf(QLatin1Char('.'), firstCnDot+1); + + // Check at least 3 components + if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length())) + return false; + + // Check * is last character of 1st component (ie. there's a following .) + if (wildcard+1 != firstCnDot) + return false; + + // Check only one star + if (cn.lastIndexOf(QLatin1Char('*')) != wildcard) + return false; + + // Check characters preceding * (if any) match + if (wildcard && (hostname.leftRef(wildcard) != cn.leftRef(wildcard))) + return false; + + // Check characters following first . match + if (hostname.midRef(hostname.indexOf(QLatin1Char('.'))) != cn.midRef(firstCnDot)) + return false; + + // Check if the hostname is an IP address, if so then wildcards are not allowed + QHostAddress addr(hostname); + if (!addr.isNull()) + return false; + + // Ok, I guess this was a wildcard CN and the hostname matches. + return true; +} + TCPSlaveBase::SslResult TCPSlaveBase::startTLSInternal(uint v_) { KTcpSocket::SslVersion sslVersion = static_cast(v_); @@ -507,7 +547,6 @@ QSslCertificate peerCert = d->socket.peerCertificateChain().first(); QStringList domainPatterns(peerCert.subjectInfo(QSslCertificate::CommonName)); domainPatterns += peerCert.alternateSubjectNames().values(QSsl::DnsEntry); - QRegExp domainMatcher(QString(), Qt::CaseInsensitive, QRegExp::Wildcard); QMutableListIterator it(d->sslErrors); while (it.hasNext()) { // As of 4.4.0 Qt does not assign a certificate to the QSslError it emits @@ -518,8 +557,7 @@ continue; } Q_FOREACH (const QString &dp, domainPatterns) { - domainMatcher.setPattern(dp); - if (domainMatcher.exactMatch(d->host)) { + if (isMatchingHostname(dp, d->host)) { it.remove(); } } Index: kio/kio/tcpslavebase.h =================================================================== --- kio/kio/tcpslavebase.h (revision 1173815) +++ kio/kio/tcpslavebase.h (working copy) @@ -198,6 +198,9 @@ // For the certificate verification code SslResult verifyServerCertificate(); + // For verifying ssl hostnames (including wildcards) + bool isMatchingHostname(const QString &cn, const QString &hostname); + // For prompting for the client certificate to use void selectClientCertificate();