[SOLVED] QsslSocket: Cannot access peer (client) certificate on other peer (server)
-
EDIT: The issue was due to bug in Qt (5.2.0). Updating Qt solved the issue (5.3.0 beta). The bug was most likely this one: https://bugreports.qt-project.org/browse/QTBUG-7200
Hi,
my goal is establishing two-ways authentication for Server+Client apps. I am having a strange problem however. Using certificates generated by XCA and OpenSSL for testing purposes in my Server+Client apps using Qt 5.2.0.
Note: I do not use QSslSocket::ignoreSslErrors() to get past the errors.
2 scenarios (:
Client has valid clientCA, valid local certificate (signed by serverCA, client template) and valid private key set.
Server has valid serverCA, valid local certificate (signed by clientCA, server template) and valid private key set.Client has valid clientCA.
Server has valid local certificate (signed by clientCA, server template) and valid private key set.
ad 1)
I can establish secure connection fine but only if I set _QSslSocket::peerVerifyMode _ to VerifyNone on server side (automatically VerifyPeer on the client).
If I do NOT do that I get assigned automatically VerifyPeer mode even though the socket is correctly evaluated as server side (checked SslMode for this). That is apparently contrary to the documentation as it says it should be automatically QueryPeer if the socket is server side. However even setting the socket to QueryPeer manually does not help and the handshake fails the same as with VerifyPeer.
Now the error I get is:
QSslError::CertificateSignatureFailed (4) "The signature of the certificate is invalid"
Inspecting the peer certificate on SSL error (and/or encrypted) on the server reveals that no certificate was presented by the peer (the peerCertificate() yields null certificate) so it is no wonder it fails with this error. I cannot get the peer certificate on client side either in this case.
BUT even if VerifyNone is set on server and encryption succeeds I still get the above mentioned error due to peer (client) not presenting its certificate despite the fact that it should NOT be requested in the first place. On client I can get peer (server) certificate in this case.
ad 2)
This is documentation style scenario, that should be capable of one way authentication only (client authenticating the server). In this case the peerVerifyMode is again selected as VerifyPeer on server by default.
However peerVerifyMode does NOT have any effect on the handshake on server side! Even when set to VerifyPeer it succeeds despite the fact that client has not presented any certificates.
No matter the setting of peerVerifyMode the error occurs the same as in #1 plus two new errors, therefore I get on server:
QSslError::CertificateSignatureFailed (4) "The signature of the certificate is invalid"
QSslError::UnableToGetLocalIssuerCertificate (11) "The issuer certificate of a locally looked up certificate could not be found"
QSslError::UnableToVerifyFirstCertificate (12) "No certificates could be verified"Despite these the SSL handshake succeeds regardless of peerVerifyMode on the server side. I get no errors on the client. This once again is contrary to the documentation that clearly states that in case of ANY SSL error the connection is dropped unless they are ignored.
I do not understand this behaviour nor how to fix it since I am fairly sure the certificates are ok (the test handshake using the openssl.exe succeeds with verify return code 0 (Ok)). It seems to me that the settings of peerVerifyMode is often ignored though and that in some cases errors are automatically ignored as well. Since they are related to unsent (or not received) peer (client) certificate on the server side I can understand it but not if the peerVerifyMode is set to VerifyPeer.
Can anybody help? Thank you!
-
Out of desperation I have tried updating the Qt to 5.3.0 beta.
Surprisingly it was in fact a bug in Qt, most likely this one: https://bugreports.qt-project.org/browse/QTBUG-7200 After trying various ways of loading the certificates I had started to get these exact same errors. With openssl s_client connect ... succeeding with return verify code 0 (Ok). So I was quite sure my certificates were fine at least.
Anywaw, I am glad I have been able to solve it.