diff options
author | Jeremy Lainé <jeremy.laine@m4x.org> | 2015-02-03 15:32:53 +0100 |
---|---|---|
committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2015-02-07 06:50:51 +0000 |
commit | cbec1ed1a15d1f4a3367bfefb694ba9a837bc501 (patch) | |
tree | 45654a84de7489fd2e54a65b55dd05fac978824d /src/network | |
parent | 14d5d4bae66b5e7571a68dd2fd9dcb7c162029dd (diff) |
ssl: fix QSslSocket::peerCertificateChain in server mode
The OpenSSL backend for QSslSocket return an incomplete peer certificate
chain when in server mode: it does not include the peer's certificate as
the first element of the chain.
This change fixes this issue.
Change-Id: I2f0815bca2f314a075b48a2d0b5a6d5b7af50722
Reviewed-by: Daniel Molkentin <daniel@molkentin.de>
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 32 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_p.h | 1 |
2 files changed, 21 insertions, 12 deletions
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index aecbebfd1f..ebf36fc34a 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -1118,11 +1118,10 @@ bool QSslSocketBackendPrivate::startHandshake() int result = (mode == QSslSocket::SslClientMode) ? q_SSL_connect(ssl) : q_SSL_accept(ssl); const QList<QPair<int, int> > &lastErrors = _q_sslErrorList()->errors; + if (!lastErrors.isEmpty()) + storePeerCertificates(); for (int i = 0; i < lastErrors.size(); ++i) { const QPair<int, int> ¤tError = lastErrors.at(i); - // Initialize the peer certificate chain in order to find which certificate caused this error - if (configuration.peerCertificateChain.isEmpty()) - configuration.peerCertificateChain = STACKOFX509_to_QSslCertificates(q_SSL_get_peer_cert_chain(ssl)); emit q->peerVerifyError(_q_OpenSSL_to_QSslError(currentError.first, configuration.peerCertificateChain.value(currentError.second))); if (q->state() != QAbstractSocket::ConnectedState) @@ -1155,15 +1154,8 @@ bool QSslSocketBackendPrivate::startHandshake() return false; } - // Store the peer certificate and chain. For clients, the peer certificate - // chain includes the peer certificate; for servers, it doesn't. Both the - // peer certificate and the chain may be empty if the peer didn't present - // any certificate. - if (configuration.peerCertificateChain.isEmpty()) - configuration.peerCertificateChain = STACKOFX509_to_QSslCertificates(q_SSL_get_peer_cert_chain(ssl)); - X509 *x509 = q_SSL_get_peer_certificate(ssl); - configuration.peerCertificate = QSslCertificatePrivate::QSslCertificate_from_X509(x509); - q_X509_free(x509); + // store peer certificate chain + storePeerCertificates(); // Start translating errors. QList<QSslError> errors; @@ -1271,6 +1263,22 @@ bool QSslSocketBackendPrivate::startHandshake() return true; } +void QSslSocketBackendPrivate::storePeerCertificates() +{ + // Store the peer certificate and chain. For clients, the peer certificate + // chain includes the peer certificate; for servers, it doesn't. Both the + // peer certificate and the chain may be empty if the peer didn't present + // any certificate. + X509 *x509 = q_SSL_get_peer_certificate(ssl); + configuration.peerCertificate = QSslCertificatePrivate::QSslCertificate_from_X509(x509); + q_X509_free(x509); + if (configuration.peerCertificateChain.isEmpty()) { + configuration.peerCertificateChain = STACKOFX509_to_QSslCertificates(q_SSL_get_peer_cert_chain(ssl)); + if (!configuration.peerCertificate.isNull() && mode == QSslSocket::SslServerMode) + configuration.peerCertificateChain.prepend(configuration.peerCertificate); + } +} + bool QSslSocketBackendPrivate::checkSslErrors() { Q_Q(QSslSocket); diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index 9564ef8566..de2bfea892 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -129,6 +129,7 @@ public: QSsl::SslProtocol sessionProtocol() const Q_DECL_OVERRIDE; void continueHandshake() Q_DECL_OVERRIDE; bool checkSslErrors(); + void storePeerCertificates(); unsigned int tlsPskClientCallback(const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len); #ifdef Q_OS_WIN void fetchCaRootForCert(const QSslCertificate &cert); |