diff --git a/src/common/connection.py b/src/common/connection.py index 339fcc901..f0d8887a3 100644 --- a/src/common/connection.py +++ b/src/common/connection.py @@ -61,6 +61,9 @@ from common import exceptions from common import check_X509 from connection_handlers import * +if gajim.HAVE_PYOPENSSL: + import OpenSSL.crypto + from nbxmpp import Smacks from string import Template import logging @@ -1382,49 +1385,49 @@ class Connection(CommonConnection, ConnectionHandlers): try: errnum = con.Connection.ssl_errnum except AttributeError: - errnum = [] # we don't have an errnum - for i, er in enumerate(errnum): - if er > 0 and str(er) not in gajim.config.get_per('accounts', - self.name, 'ignore_ssl_errors').split(): - text = _('The authenticity of the %s certificate could be ' - 'invalid.') % hostname - if er in ssl_error: - text += _('\nSSL Error: %s') % ssl_error[er] - else: - text += _('\nUnknown SSL error: %d') % er - gajim.nec.push_incoming_event(SSLErrorEvent(None, conn=self, - error_text=text, error_num=er, - cert=con.Connection.ssl_cert_pem[i], - fingerprint=con.Connection.ssl_fingerprint_sha1[i], - certificate=con.Connection.ssl_certificate[i])) - return True - if con.Connection.ssl_fingerprint_sha1: + errnum = 0 + cert = con.Connection.ssl_certificate + if errnum > 0 and str(errnum) not in gajim.config.get_per('accounts', + self.name, 'ignore_ssl_errors').split(): + text = _('The authenticity of the %s certificate could be invlid') \ + % hostname + if errnum in ssl_error: + text += _('\nSSL Error: %s') % ssl_error[errnum] + else: + text += _('\nUnknown SSL error: %d') % errnum + fingerprint = cert.digest('sha1') + pem = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, + cert) + gajim.nec.push_incoming_event(SSLErrorEvent(None, conn=self, + error_text=text, error_num=errnum, cert=pem, + fingerprint=fingerprint, certificate=cert)) + return True + if cert: + fingerprint = cert.digest('sha1') saved_fingerprint = gajim.config.get_per('accounts', self.name, 'ssl_fingerprint_sha1') if saved_fingerprint: # Check sha1 fingerprint - if con.Connection.ssl_fingerprint_sha1[-1] != saved_fingerprint: + if fingerprint != saved_fingerprint: gajim.nec.push_incoming_event(FingerprintErrorEvent(None, - conn=self, - certificate=con.Connection.ssl_certificate[-1], - new_fingerprint=con.Connection.ssl_fingerprint_sha1[ - -1])) + conn=self, certificate=con.Connection.ssl_certificate, + new_fingerprint=fingerprint)) return True else: gajim.config.set_per('accounts', self.name, - 'ssl_fingerprint_sha1', - con.Connection.ssl_fingerprint_sha1[-1]) - if not check_X509.check_certificate(con.Connection.ssl_certificate[ - -1], hostname) and '100' not in gajim.config.get_per('accounts', + 'ssl_fingerprint_sha1', fingerprint) + if not check_X509.check_certificate(con.Connection.ssl_certificate, + hostname) and '100' not in gajim.config.get_per('accounts', self.name, 'ignore_ssl_errors').split(): + fingerprint = cert.digest('sha1') + pem = OpenSSL.crypto.dump_certificate( + OpenSSL.crypto.FILETYPE_PEM, cert) txt = _('The authenticity of the %s certificate could be ' 'invalid.\nThe certificate does not cover this domain.') % \ hostname gajim.nec.push_incoming_event(SSLErrorEvent(None, conn=self, - error_text=txt, error_num=100, - cert=con.Connection.ssl_cert_pem[-1], - fingerprint=con.Connection.ssl_fingerprint_sha1[-1], - certificate=con.Connection.ssl_certificate[-1])) + error_text=txt, error_num=100, cert=pem, + fingerprint=fingerprint, certificate=cert)) return True self._register_handlers(con, con_type) diff --git a/src/common/connection_handlers_events.py b/src/common/connection_handlers_events.py index 8a9202e5c..d3d9456dc 100644 --- a/src/common/connection_handlers_events.py +++ b/src/common/connection_handlers_events.py @@ -1600,20 +1600,19 @@ class NewAccountConnectedEvent(nec.NetworkIncomingEvent): try: self.errnum = self.conn.connection.Connection.ssl_errnum except AttributeError: - self.errnum = [] # we don't have an errnum + self.errnum = 0 # we don't have an errnum self.ssl_msg = '' - for er in self.errnum: - if er > 0: - from common.connection import ssl_error - self.ssl_msg = ssl_error.get(er, _('Unknown SSL error: %d') % \ - er) + if self.errnum > 0: + from common.connection import ssl_error + self.ssl_msg = ssl_error.get(er, _('Unknown SSL error: %d') % \ + self.errnum) self.ssl_cert = '' if len(self.conn.connection.Connection.ssl_cert_pem): self.ssl_cert = self.conn.connection.Connection.ssl_cert_pem self.ssl_fingerprint = '' - if len(self.conn.connection.Connection.ssl_fingerprint_sha1): + if self.conn.connection.Connection.ssl_certificate: self.ssl_fingerprint = \ - self.conn.connection.Connection.ssl_fingerprint_sha1 + self.conn.connection.Connection.ssl_certificate.digest('sha1') return True class NewAccountNotConnectedEvent(nec.NetworkIncomingEvent): diff --git a/src/common/gajim.py b/src/common/gajim.py index 1126970bf..84f729ea5 100644 --- a/src/common/gajim.py +++ b/src/common/gajim.py @@ -172,6 +172,17 @@ else: if subprocess.call(gpg_cmd, shell=True): HAVE_GPG = False +HAVE_PYOPENSSL = True +try: + import OpenSSL.SSL + import OpenSSL.crypto + ver = OpenSSL.__version__ + ver_l = [int(i) for i in ver.split('.')] + if ver_l < [0, 12]: + raise ImportError +except Exception: + HAVE_PYOPENSSL = False + HAVE_FARSTREAM = True try: farstream = __import__('farstream')