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 <rich@kde.org>
bb10
Timur Pocheptsov 2015-03-02 17:29:55 +01:00
parent fd6a2d1c8f
commit 53207e820c
2 changed files with 18 additions and 4 deletions

View File

@ -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();

View File

@ -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();