Fix/workaround a quirk in SecureTransport

We set anchors from QSslConfiguration::caCertificates. On macOS these
anchors are by default copied from the system store, so I expected
setting 'trust those anchors only' should not break anything.
Somehow, on 10.11 SecTrustEvaluate fails to evaluate a valid
certificate chain (apparently because it has an intermediate
certificate, it's just a guess, since their API/docs are too poor
to explain well what was the real cause) as I can see connecting,
for example, to google.com - we have a chain with a valid root,
say it's GetTrust CA and we have it also in our list of anchors we set
on trust, but evaluation fails with: kSecTrustResultRecoverableTrustFailure:

"This means that you should not trust the chain as-is, but that
the chain could be trusted with some minor change to the evaluation
context, such as ignoring expired certificates or adding an
additional anchor to the set of trusted anchors."

Since none of certs is expired, and the required anchor already set,
this must be some bug in SecureTransport. For macOS (deployment
target) < 10.12 we fallback to the original version of the code
(the one that unfortunately does not allow us to limit the set
of trusted anchors by what client code wants to trust).

Change-Id: Ie42fd77c3eb6ef7469812aa0d7efff88a003c0b8
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
Timur Pocheptsov 2017-12-07 17:01:38 +01:00
parent 9dc7904556
commit 2086c183c1

View File

@ -47,6 +47,7 @@
#include "qsslkey_p.h"
#include <QtCore/qmessageauthenticationcode.h>
#include <QtCore/qoperatingsystemversion.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qdatastream.h>
#include <QtCore/qsysinfo.h>
@ -1247,13 +1248,17 @@ bool QSslSocketBackendPrivate::verifyPeerTrust()
// 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.
// the default behavior. Note, with macOS SDK below 10.12 using 'trust my
// anchors only' may result in some valid chains rejected, apparently the
// ones containing intermediated certificates; so we use this functionality
// on more recent versions only.
bool anchorsFromConfigurationOnly = false;
#ifdef Q_OS_MACOS
const bool anchorsFromConfigurationOnly = true;
#else
const bool anchorsFromConfigurationOnly = false;
#endif
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra)
anchorsFromConfigurationOnly = true;
#endif // Q_OS_MACOS
SecTrustSetAnchorCertificatesOnly(trust, anchorsFromConfigurationOnly);