Priority: P2: Important
Affects Version/s: 5.14.0, 5.15.1
Component/s: Network: SSL
Commits:1158ff67b492853b72199ed78bfcf24132e1c7ff (qt/qtbase/dev) 65e2837b30becb745036f13d98a9472a0332b152 (qt/qtbase/6.0.0) 94983639fc559fd57c6075b1323b28f034a49071 (qt/qtbase/6.0) f4152d268e842961597b53819f2821df9804e303 (qt/qtbase/5.15)
In order to validate that an SSL certificate belongs to a specific root certificate, you can set the list of trusted root certificate using the (now deprecated) QSslSocket::setDefaultCaCertificates static method. This makes sure that further certificate validation uses only the root certificate list given.
After the above method has been deprecated, I believe that the QSslConfiguration:: setCaCertificates() method should be used instead in a manner like this:
However, at least on the Windows platform, this does not make QT exclude the trusted root certificates retrieved from the Windows certificate store. This is a problem if you need to validate that a certificate is based on a specific set of root certificates (as certificate chains ending in a certificate in the Windows store will be validatable as well).
Find attached a small project that illustrates the problem. The project includes a self-signed root certificate. With this set up as the only trusted certificate (using either of the two methods above), the official certificate found on www.qt.io is validated. The validation should fail, as the qt.io certificate chain does not end in the specified root certificate. However if the root certificate is set through QSslConfiguration::setCaCertificates, the validation succeeds, as it can be validated against the root certificates in the Windows store.
Using the old setDefaultCaCertificates method, the validation fails as expected.
The problem seems to be related to the QSslSocketPrivate::s_loadRootCertsOnDemand variable, which appears to be reset by QSslSocket::setDefaultCaCertificates, but not by QSslConfiguration::setCaCertificates.
In the attached test application, the two methods can be tested by switching between “#if 0” and “#if 1”. After setting the root certificate, tests are performed using QSslCertificate::verify as well as a QSslSocket-connection to www.qt.io.
A working libssl/libcrypto DLL set must be available when testing the application. I was using openssl 1.1.1g in my test.
|For Gerrit Dashboard: QTBUG-88639|
|322640,9||QSslSocket::verify: do not alter the default configuration||dev||qt/qtbase||Status: MERGED||+2||0|
|324408,2||QSslSocket::verify: do not alter the default configuration||6.0||qt/qtbase||Status: MERGED||+2||0|
|324409,2||QSslSocket::verify: do not alter the default configuration||6.0.0||qt/qtbase||Status: MERGED||+2||0|
|324410,5||QSslSocket::verify: do not alter the default configuration||5.15||qt/qtbase||Status: MERGED||+2||0|