diff options
Diffstat (limited to 'src/network/ssl/qsslsocket.cpp')
-rw-r--r-- | src/network/ssl/qsslsocket.cpp | 112 |
1 files changed, 110 insertions, 2 deletions
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 90f6e25b97..b092e5e980 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Copyright (C) 2014 BlackBerry Limited. All rights reserved. ** Contact: http://www.qt-project.org/legal ** @@ -291,7 +291,12 @@ #include "qsslsocket.h" #include "qsslcipher.h" +#ifndef QT_NO_OPENSSL #include "qsslsocket_openssl_p.h" +#endif +#ifdef Q_OS_WINRT +#include "qsslsocket_winrt_p.h" +#endif #include "qsslconfiguration_p.h" #include <QtCore/qdebug.h> @@ -880,6 +885,7 @@ QSslConfiguration QSslSocket::sslConfiguration() const QSslConfigurationPrivate *copy = new QSslConfigurationPrivate(d->configuration); copy->ref.store(0); // the QSslConfiguration constructor refs up copy->sessionCipher = d->sessionCipher(); + copy->sessionProtocol = d->sessionProtocol(); return QSslConfiguration(copy); } @@ -1075,6 +1081,20 @@ QSslCipher QSslSocket::sessionCipher() const } /*! + Returns the socket's SSL/TLS protocol or UnknownProtocol if the + connection isn't encrypted. The socket's protocol for the session + is set during the handshake phase. + + \sa protocol(), setProtocol() +*/ +QSsl::SslProtocol QSslSocket::sessionProtocol() const +{ + Q_D(const QSslSocket); + return d->sessionProtocol(); +} + + +/*! Sets the socket's private \l {QSslKey} {key} to \a key. The private key and the local \l {QSslCertificate} {certificate} are used by clients and servers that must prove their identity to @@ -1667,6 +1687,32 @@ QString QSslSocket::sslLibraryVersionString() } /*! + \since 5.4 + Returns the version number of the SSL library in use at compile + time. If no SSL support is available then this will return an + undefined value. + + \sa sslLibraryVersionNumber() +*/ +long QSslSocket::sslLibraryBuildVersionNumber() +{ + return QSslSocketPrivate::sslLibraryBuildVersionNumber(); +} + +/*! + \since 5.4 + Returns the version string of the SSL library in use at compile + time. If no SSL support is available then this will return an + empty value. + + \sa sslLibraryVersionString() +*/ +QString QSslSocket::sslLibraryBuildVersionString() +{ + return QSslSocketPrivate::sslLibraryBuildVersionString(); +} + +/*! Starts a delayed SSL handshake for a client connection. This function can be called when the socket is in the \l ConnectedState but still in the \l UnencryptedMode. If it is not yet connected, @@ -1848,8 +1894,10 @@ void QSslSocket::disconnectFromHost() emit stateChanged(d->state); } - if (!d->writeBuffer.isEmpty()) + if (!d->writeBuffer.isEmpty()) { + d->pendingClose = true; return; + } if (d->mode == UnencryptedMode) { d->plainSocket->disconnectFromHost(); @@ -2098,6 +2146,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri ptr->localCertificateChain = global->localCertificateChain; ptr->privateKey = global->privateKey; ptr->sessionCipher = global->sessionCipher; + ptr->sessionProtocol = global->sessionProtocol; ptr->ciphers = global->ciphers; ptr->caCertificates = global->caCertificates; ptr->protocol = global->protocol; @@ -2466,6 +2515,65 @@ QSharedPointer<QSslContext> QSslSocketPrivate::sslContext(QSslSocket *socket) return (socket) ? socket->d_func()->sslContextPointer : QSharedPointer<QSslContext>(); } +bool QSslSocketPrivate::isMatchingHostname(const QSslCertificate &cert, const QString &peerName) +{ + QStringList commonNameList = cert.subjectInfo(QSslCertificate::CommonName); + + foreach (const QString &commonName, commonNameList) { + if (isMatchingHostname(commonName.toLower(), peerName.toLower())) { + return true; + } + } + + foreach (const QString &altName, cert.subjectAlternativeNames().values(QSsl::DnsEntry)) { + if (isMatchingHostname(altName.toLower(), peerName.toLower())) { + return true; + } + } + + return false; +} + +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; + + 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; +} + QT_END_NAMESPACE #include "moc_qsslsocket.cpp" |