Ssl socket - fix broken certificate verification

On iOS QSslConfiguration always has an empty list of system CA certificates.
Calling SecTrustSetAnchorCertificatesOnly(.., TRUE) on iOS  results in
SecTrustEvaluate failing to verify a valid certificate, since there
are no 'anchors' at all. We can use SecTrustSetAnchorCerificatesOnly(.. TRUE)
on macOS only, where we do extract/copy system certificates using
SecTrustSettingsCopyCertificates and save them in a QSslConfiguration's
list.

Task-number: QTBUG-61053
Change-Id: I70d4e46273d78414baaac8531273def707c3eebc
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Timur Pocheptsov 2017-06-01 12:04:06 +02:00
parent 91ef71b7bf
commit 4fb1745639

View File

@ -1222,9 +1222,32 @@ bool QSslSocketBackendPrivate::verifyPeerTrust()
QCFType<SecCertificateRef> certRef = SecCertificateCreateWithData(NULL, certData);
CFArrayAppendValue(certArray, certRef);
}
SecTrustSetAnchorCertificates(trust, certArray);
// Secure Transport should use anchors only from our QSslConfiguration:
SecTrustSetAnchorCertificatesOnly(trust, true);
// By default SecTrustEvaluate uses both CA certificates provided in
// QSslConfiguration and the ones from the system database. This behavior can
// be unexpected if a user's code tries to limit the trusted CAs to those
// explicitly set in QSslConfiguration.
// Since on macOS we initialize the default QSslConfiguration copying the
// system CA certificates (using SecTrustSettingsCopyCertificates) we can
// call SecTrustSetAnchorCertificatesOnly(trust, true) to force SecTrustEvaluate
// to use anchors only from our QSslConfiguration.
// Unfortunately, SecTrustSettingsCopyCertificates is not available on iOS
// and the default QSslConfiguration always has an empty list of system CA
// certificates. This leaves no way to provide client code with access to the
// actual system CA certificate list (which most use-cases need) other than
// by letting SecTrustEvaluate fall through to the system list; so, in this case
// (even though the client code may have provided its own certs), we retain
// the default behavior.
#ifdef Q_OS_MACOS
const bool anchorsFromConfigurationOnly = true;
#else
const bool anchorsFromConfigurationOnly = false;
#endif
SecTrustSetAnchorCertificatesOnly(trust, anchorsFromConfigurationOnly);
SecTrustResultType trustResult = kSecTrustResultInvalid;
SecTrustEvaluate(trust, &trustResult);