Gajim fails to handle invalid certificates
Bug description
Gajim does not seem to properly handle invalid/broken/expired certificates. The _ssl_verify_callback function in tls_nb.py is called by OpenSSL for every certificate in the certificate chain (CA first, server certificate last) but always return True whether an error was encountered or not.
This forces OpenSSL to verify each certificate until none is left, at which points it will call _ssl_verify_callback one last time with an error number of 0.
(This behavior is documented here: "man 3 SSL_CTX_set_verify"
"If verify_callback returns 1, the verification process is continued. If verify_callback always returns 1, the TLS/SSL handshake will not be terminated with respect to verification failures and the connection will be established."
And can be observed in function crypto/x509/x509_vfy.c:internal_verify() in OpenSSL source code.)
_ssh_verify_callback only stores the last error code, which always is 0 unless an error was encountered in the deepest level of the chain (the CA), so gajim will not warn as long as the CA is recognized.
Steps to reproduce
To confirm this behavior, add at the begining of _ssl_verify_callback:
self._dumpX509(cert)
print >>self.stderr, "Args:", errnum, depth, ok, '\n-------'
And try to connect to a server with an invalid server certificate (for example, an expired one). You will observe the following:
Digest (SHA-1): {CA cert fingerprint}
(...)
Expired: No
Subject:
X509Name: {The CA Name}
(...)
Args: 0 1 1
-----------------------------
Digest (SHA-1): {Server cert fingerprint}
(...)
Expired: Yes
Subject:
X509Name: {The Server's CN}
(...)
Args: 10 0 0
-----------------------------
Digest (SHA-1): {Server cert fingerprint again}
(...)
Expired: Yes
Subject:
X509Name: {The Server's CN again}
(...)
Args: 0 0 1
-----------------------------
You can see that _ssl_verify_callback is called with an errnum of 10 (meaning expired certificate), but since it returns True and OpenSSL has reached the last certificate in the chain, OpenSSL calls it one last time with an error code of 0 and the "ok" argument set to 1.
This problem goes beyond expired certificates. It is also possible to edit any existing and valid server certificate by changing the CN manually. The certificate's signature will be become invalid and OpenSSL will detect it and return errnum 7 ("Certificate signature failure") but gajim will not warn and will proceed with the connection anyway...