From 53207e820c894a1408aa77aa2237cc664eabc119 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Mon, 2 Mar 2015 17:29:55 +0100 Subject: [PATCH] Secure Transport - handle errSSLBadCert in server mode Suddenly :(( With Security Framework v 7.0 dated by 17/02 SSLHandshake works differently when our server socket is requesting a client side authentication and client provides no certificate. Despite of kTryAuthenticate (this means, auth. _can_ fail) server receives an error from SSLHandshake too early. We have to handle this in startHandshake (when serveMode && canIgnore). Change-Id: Ie55540078e2944e80cf2f4ade8b000acf29d6ca2 Reviewed-by: Richard J. Moore --- src/network/ssl/qsslsocket_mac.cpp | 21 +++++++++++++++++---- src/network/ssl/qsslsocket_mac_p.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 3326362d66..e833bb70c5 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -942,6 +942,15 @@ bool QSslSocketBackendPrivate::setSessionProtocol() return err == noErr; } +bool QSslSocketBackendPrivate::canIgnoreTrustVerificationFailure() const +{ + const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode; + return mode == QSslSocket::SslServerMode + && (verifyMode == QSslSocket::QueryPeer + || verifyMode == QSslSocket::AutoVerifyPeer + || verifyMode == QSslSocket::VerifyNone); +} + bool QSslSocketBackendPrivate::verifySessionProtocol() const { bool protocolOk = false; @@ -962,10 +971,7 @@ bool QSslSocketBackendPrivate::verifyPeerTrust() Q_Q(QSslSocket); const QSslSocket::PeerVerifyMode verifyMode = configuration.peerVerifyMode; - const bool canIgnoreVerify = mode == QSslSocket::SslServerMode - && (verifyMode == QSslSocket::QueryPeer - || verifyMode == QSslSocket::AutoVerifyPeer - || verifyMode == QSslSocket::VerifyNone); + const bool canIgnoreVerify = canIgnoreTrustVerificationFailure(); Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)"); Q_ASSERT(plainSocket); @@ -1164,6 +1170,13 @@ bool QSslSocketBackendPrivate::startHandshake() return startHandshake(); } } else if (err != errSecSuccess) { + if (err == errSSLBadCert && canIgnoreTrustVerificationFailure()) { + // We're on the server side and client did not provide any + // certificate. This is the new 'nice' error returned by + // Security Framework after it was recently updated. + return startHandshake(); + } + setError(QStringLiteral("Error during SSL handshake: %1").arg(err), QAbstractSocket::SslHandshakeFailedError); plainSocket->disconnectFromHost(); diff --git a/src/network/ssl/qsslsocket_mac_p.h b/src/network/ssl/qsslsocket_mac_p.h index 4901a8576f..868b816957 100644 --- a/src/network/ssl/qsslsocket_mac_p.h +++ b/src/network/ssl/qsslsocket_mac_p.h @@ -94,6 +94,7 @@ private: QAbstractSocket::SocketError &errorCode); bool setSessionProtocol(); // Aux. functions to do a verification during handshake phase: + bool canIgnoreTrustVerificationFailure() const; bool verifySessionProtocol() const; bool verifyPeerTrust();