From 233a2f37bfa6c896612cbf9a7db42e8e0da788f5 Mon Sep 17 00:00:00 2001 From: "Richard J. Moore" Date: Mon, 10 Mar 2014 13:00:08 +0000 Subject: Add support for finding the version of SSL/TLS in use. Previously we allowed you to specify which version(s) you wanted to use, but did not provide access to the version that was actually negotiated. [ChangeLog][QtNetwork][QSslSocket] Add support for finding the version of SSL/TLS in use by a connection. Task-number: QTBUG-28471 Change-Id: I6d50d2bc9f1ce7f98192e67992178fe7e41c0575 Reviewed-by: Peter Hartmann --- src/network/ssl/qsslconfiguration.cpp | 13 +++++++++++++ src/network/ssl/qsslconfiguration.h | 1 + src/network/ssl/qsslconfiguration_p.h | 4 +++- src/network/ssl/qsslsocket.cpp | 16 ++++++++++++++++ src/network/ssl/qsslsocket.h | 1 + src/network/ssl/qsslsocket_openssl.cpp | 22 ++++++++++++++++++++++ src/network/ssl/qsslsocket_openssl_p.h | 1 + src/network/ssl/qsslsocket_openssl_symbols.cpp | 2 ++ src/network/ssl/qsslsocket_openssl_symbols_p.h | 1 + src/network/ssl/qsslsocket_p.h | 1 + 10 files changed, 61 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index 1e859ae6e6..3b59b0e3ce 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -208,6 +208,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const d->localCertificateChain == other.d->localCertificateChain && d->privateKey == other.d->privateKey && d->sessionCipher == other.d->sessionCipher && + d->sessionProtocol == other.d->sessionProtocol && d->ciphers == other.d->ciphers && d->caCertificates == other.d->caCertificates && d->protocol == other.d->protocol && @@ -511,6 +512,18 @@ QSslCipher QSslConfiguration::sessionCipher() const return d->sessionCipher; } +/*! + 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 QSslConfiguration::sessionProtocol() const +{ + return d->sessionProtocol; +} + /*! Returns the \l {QSslKey} {SSL key} assigned to this connection or a null key if none has been assigned yet. diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index 587187ca06..4c5799bf28 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -109,6 +109,7 @@ public: QSslCertificate peerCertificate() const; QList peerCertificateChain() const; QSslCipher sessionCipher() const; + QSsl::SslProtocol sessionProtocol() const; // Private keys, for server sockets QSslKey privateKey() const; diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h index d183c3335c..29bd4053ad 100644 --- a/src/network/ssl/qsslconfiguration_p.h +++ b/src/network/ssl/qsslconfiguration_p.h @@ -81,7 +81,8 @@ class QSslConfigurationPrivate: public QSharedData { public: QSslConfigurationPrivate() - : protocol(QSsl::SecureProtocols), + : sessionProtocol(QSsl::UnknownProtocol), + protocol(QSsl::SecureProtocols), peerVerifyMode(QSslSocket::AutoVerifyPeer), peerVerifyDepth(0), allowRootCertOnDemandLoading(true), @@ -98,6 +99,7 @@ public: QSslKey privateKey; QSslCipher sessionCipher; + QSsl::SslProtocol sessionProtocol; QList ciphers; QList caCertificates; diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 6edf4efae0..d1f010812e 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -878,6 +878,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); } @@ -1072,6 +1073,20 @@ QSslCipher QSslSocket::sessionCipher() const return d->sessionCipher(); } +/*! + 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 @@ -2095,6 +2110,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; diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index d89933efda..6fd639b024 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -140,6 +140,7 @@ public: QSslCertificate peerCertificate() const; QList peerCertificateChain() const; QSslCipher sessionCipher() const; + QSsl::SslProtocol sessionProtocol() const; // Private keys, for server sockets. void setPrivateKey(const QSslKey &key); diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 3421154114..58c2557ad5 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1428,6 +1428,28 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher(); } +QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const +{ + if (!ssl) + return QSsl::UnknownProtocol; + int ver = q_SSL_version(ssl); + + switch (ver) { + case 0x2: + return QSsl::SslV2; + case 0x300: + return QSsl::SslV3; + case 0x301: + return QSsl::TlsV1_0; + case 0x302: + return QSsl::TlsV1_1; + case 0x303: + return QSsl::TlsV1_2; + } + + return QSsl::UnknownProtocol; +} + void QSslSocketBackendPrivate::continueHandshake() { Q_Q(QSslSocket); diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index c8b23e6cad..0a9d02287d 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -131,6 +131,7 @@ public: void disconnectFromHost(); void disconnected(); QSslCipher sessionCipher() const; + QSsl::SslProtocol sessionProtocol() const; void continueHandshake(); bool checkSslErrors(); #ifdef Q_OS_WIN diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 79bce22b0d..3c7402cd26 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -238,6 +238,7 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, retu #else DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return) #endif +DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return) DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return) DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return) DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return) @@ -739,6 +740,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_free) RESOLVEFUNC(SSL_get_ciphers) RESOLVEFUNC(SSL_get_current_cipher) + RESOLVEFUNC(SSL_version) RESOLVEFUNC(SSL_get_error) RESOLVEFUNC(SSL_get_peer_cert_chain) RESOLVEFUNC(SSL_get_peer_certificate) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 500fe9493b..c363694bf6 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -329,6 +329,7 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a); #else SSL_CIPHER *q_SSL_get_current_cipher(SSL *a); #endif +int q_SSL_version(const SSL *a); int q_SSL_get_error(SSL *a, int b); STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a); X509 *q_SSL_get_peer_certificate(SSL *a); diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 6281753225..83c88d86bc 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -190,6 +190,7 @@ public: virtual void disconnectFromHost() = 0; virtual void disconnected() = 0; virtual QSslCipher sessionCipher() const = 0; + virtual QSsl::SslProtocol sessionProtocol() const = 0; virtual void continueHandshake() = 0; Q_AUTOTEST_EXPORT static bool rootCertOnDemandLoadingSupported(); -- cgit v1.2.3