Ticket #720: ssl_cert_verif.2.diff
| File ssl_cert_verif.2.diff, 11.5 KB (added by asterix, 2 years ago) |
|---|
-
gajim.py
2166 2166 instance = data[1] 2167 2167 instance.unique_room_id_error(data[0]) 2168 2168 2169 def handle_event_ssl_error(self, account, data): 2170 # ('SSL_ERROR', account, (text, cert, sha1_fingerprint)) 2171 server = gajim.config.get_per('accounts', account, 'hostname') 2172 def on_ok(is_checked): 2173 if is_checked: 2174 f = open(gajim.MY_CACERTS, 'a') 2175 f.write(server + '\n') 2176 f.write(data[1] + '\n\n') 2177 f.close() 2178 gajim.config.set_per('accounts', account, 'ssl_fingerprint_sha1', 2179 data[2]) 2180 gajim.connections[account].ssl_certificate_accepted() 2181 def on_cancel(): 2182 gajim.connections[account].disconnect(on_purpose=True) 2183 self.handle_event_status(account, 'offline') 2184 pritext = _('Error verifying SSL certificate') 2185 sectext = _('There was an error verifying the SSL certificate of your jabber server: %(error)s\nDo you still want to connect to this server?') % {'error': data[0]} 2186 checktext = _('Add this certificate to the list of trusted certificates.\nSHA1 fingerprint of the certificate:\n%s') % data[2] 2187 dialogs.ConfirmationDialogCheck(pritext, sectext, checktext, 2188 on_response_ok=on_ok, on_response_cancel=on_cancel) 2189 2190 def handle_event_fingerprint_error(self, account, data): 2191 # ('FINGERPRINT_ERROR', account, (fingerprint,)) 2192 def on_yes(widget): 2193 dialog.destroy() 2194 gajim.config.set_per('accounts', account, 'ssl_fingerprint_sha1', 2195 data[0]) 2196 gajim.connections[account].ssl_certificate_accepted() 2197 def on_no(widget): 2198 dialog.destroy() 2199 gajim.connections[account].disconnect(on_purpose=True) 2200 self.handle_event_status(account, 'offline') 2201 pritext = _('SSL certificate error') 2202 sectext = _('It seems SSL certificate has changed or your connection is ' 2203 'being hacked. Do you still want to connect and update the fingerprint' 2204 'of the certificate?') 2205 dialog = dialogs.YesNoDialog(pritext, sectext, on_response_yes=on_yes, 2206 on_response_no=on_no) 2207 2169 2208 def read_sleepy(self): 2170 2209 '''Check idle status and change that status if needed''' 2171 2210 if not self.sleeper.poll(): … … 2502 2541 'UNIQUE_ROOM_ID_SUPPORTED': self.handle_event_unique_room_id_supported, 2503 2542 'SESSION_NEG': self.handle_session_negotiation, 2504 2543 'GPG_PASSWORD_REQUIRED': self.handle_event_gpg_password_required, 2544 'SSL_ERROR': self.handle_event_ssl_error, 2545 'FINGERPRINT_ERROR': self.handle_event_fingerprint_error, 2505 2546 } 2506 2547 gajim.handlers = self.handlers 2507 2548 -
common/xmpp/transports_nb.py
745 745 #tcpsock._sslContext = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD) 746 746 tcpsock.ssl_errnum = 0 747 747 tcpsock._sslContext.set_verify(OpenSSL.SSL.VERIFY_PEER, self._ssl_verify_callback) 748 cacerts = os.path.join(gajim.DATA_DIR, 'other', 'cacerts.pem') 748 749 try: 749 tcpsock._sslContext.load_verify_locations( os.path.join(gajim.DATA_DIR, 'other', 'cacerts.pem'))750 tcpsock._sslContext.load_verify_locations(cacerts) 750 751 except: 751 log.warning(_("Unable to load SSL certificats from file %s" % os.path.abspath(os.path.join(gajim.DATA_DIR,'other','ca.crt')))) 752 log.warning('Unable to load SSL certificats from file %s' % \ 753 os.path.abspath(cacerts)) 754 # load users certs 755 if os.path.isfile(gajim.MY_CACERTS): 756 store = tcpsock._sslContext.get_cert_store() 757 f = open(gajim.MY_CACERTS) 758 lines = f.readlines() 759 i = 0 760 begin = -1 761 for line in lines: 762 if 'BEGIN CERTIFICATE' in line: 763 begin = i 764 continue 765 elif 'END CERTIFICATE' in line and begin > -1: 766 cert = ''.join(lines[begin:i+2]) 767 try: 768 X509cert = OpenSSL.crypto.load_certificate( 769 OpenSSL.crypto.FILETYPE_PEM, cert) 770 store.add_cert(X509cert) 771 except: 772 log.warning('Unable to load a certificate from file %s' % \ 773 gajim.MY_CACERTS) 774 begin = -1 775 i += 1 752 776 tcpsock._sslObj = OpenSSL.SSL.Connection(tcpsock._sslContext, tcpsock._sock) 753 777 tcpsock._sslObj.set_connect_state() # set to client mode 754 778 … … 788 812 def _ssl_verify_callback(self, sslconn, cert, errnum, depth, ok): 789 813 # Exceptions can't propagate up through this callback, so print them here. 790 814 try: 815 self._owner.Connection.ssl_fingerprint_sha1 = cert.digest('sha1') 791 816 if errnum == 0: 792 817 return True 793 818 self._owner.Connection.ssl_errnum = errnum 819 self._owner.Connection.ssl_cert_pem = OpenSSL.crypto.dump_certificate( 820 OpenSSL.crypto.FILETYPE_PEM, cert) 794 821 return True 795 822 except: 796 823 log.error("Exception caught in _ssl_info_callback:", exc_info=True) -
common/configpaths.py
79 79 80 80 # LOG is deprecated 81 81 k = ( 'LOG', 'LOG_DB', 'VCARD', 'AVATAR', 'MY_EMOTS', 82 'MY_ICONSETS' )82 'MY_ICONSETS', 'MY_CACERTS') 83 83 v = (u'logs', u'logs.db', u'vcards', u'avatars', u'emoticons', 84 u'iconsets' )84 u'iconsets', u'cacerts.pem') 85 85 86 86 if os.name == 'nt': 87 87 v = map(lambda x: x.capitalize(), v) -
common/config.py
276 276 'keyid': [ opt_str, '', '', True ], 277 277 'keyname': [ opt_str, '', '', True ], 278 278 'usessl': [ opt_bool, False, '', True ], 279 'ssl_fingerprint_sha1': [ opt_str, '', '', True ], 279 280 'use_srv': [ opt_bool, True, '', True ], 280 281 'use_custom_host': [ opt_bool, False, '', True ], 281 282 'custom_port': [ opt_int, 5222, '', True ], -
common/gajim.py
77 77 AVATAR_PATH = gajimpaths['AVATAR'] 78 78 MY_EMOTS_PATH = gajimpaths['MY_EMOTS'] 79 79 MY_ICONSETS_PATH = gajimpaths['MY_ICONSETS'] 80 MY_CACERTS = gajimpaths['MY_CACERTS'] 80 81 TMP = gajimpaths['TMP'] 81 82 DATA_DIR = gajimpaths['DATA'] 82 83 HOME_DIR = gajimpaths['HOME'] -
common/connection.py
59 59 import gtkgui_helpers 60 60 61 61 ssl_error = { 62 2: "Unable to get issuer certificate",63 3: "Unable to get certificate CRL",64 4: "Unable to decrypt certificate's signature",65 5: "Unable to decrypt CRL's signature",66 6: "Unable to decode issuer public key",67 7: "Certificate signature failure",68 8: "CRL signature failure",69 9: "Certificate is not yet valid",70 10: "Certificate has expired",71 11: "CRL is not yet valid",72 12: "CRL has expired",73 13: "Format error in certificate's notBefore field",74 14: "Format error in certificate's notAfter field",75 15: "Format error in CRL's lastUpdate field",76 16: "Format error in CRL's nextUpdate field",77 17: "Out of memory",78 18: "Self signed certificate in certificate chain",79 19: "Unable to get local issuer certificate",80 20: "Unable to verify the first certificate",81 21: "Unable to verify the first certificate",82 22: "Certificate chain too long",83 23: "Certificate revoked",84 24: "Invalid CA certificate",85 25: "Path length constraint exceeded",86 26: "Unsupported certificate purpose",87 27: "Certificate not trusted",88 28: "Certificate rejected",89 29: "Subject issuer mismatch",90 30: "Authority and subject key identifier mismatch",91 31: "Authority and issuer serial number mismatch",92 32: "Key usage does not include certificate signing",93 50: "Application verification failure"62 2: _("Unable to get issuer certificate"), 63 3: _("Unable to get certificate CRL"), 64 4: _("Unable to decrypt certificate's signature"), 65 5: _("Unable to decrypt CRL's signature"), 66 6: _("Unable to decode issuer public key"), 67 7: _("Certificate signature failure"), 68 8: _("CRL signature failure"), 69 9: _("Certificate is not yet valid"), 70 10: _("Certificate has expired"), 71 11: _("CRL is not yet valid"), 72 12: _("CRL has expired"), 73 13: _("Format error in certificate's notBefore field"), 74 14: _("Format error in certificate's notAfter field"), 75 15: _("Format error in CRL's lastUpdate field"), 76 16: _("Format error in CRL's nextUpdate field"), 77 17: _("Out of memory"), 78 18: _("Self signed certificate in certificate chain"), 79 19: _("Unable to get local issuer certificate"), 80 20: _("Unable to verify the first certificate"), 81 21: _("Unable to verify the first certificate"), 82 22: _("Certificate chain too long"), 83 23: _("Certificate revoked"), 84 24: _("Invalid CA certificate"), 85 25: _("Path length constraint exceeded"), 86 26: _("Unsupported certificate purpose"), 87 27: _("Certificate not trusted"), 88 28: _("Certificate rejected"), 89 29: _("Subject issuer mismatch"), 90 30: _("Authority and subject key identifier mismatch"), 91 31: _("Authority and issuer serial number mismatch"), 92 32: _("Key usage does not include certificate signing"), 93 50: _("Application verification failure") 94 94 } 95 95 class Connection(ConnectionHandlers): 96 96 '''Connection class''' … … 182 182 self.retrycount = 0 183 183 184 184 # We are doing disconnect at so many places, better use one function in all 185 def disconnect(self, on_purpose =False):185 def disconnect(self, on_purpose=False): 186 186 self.on_purpose = on_purpose 187 187 self.connected = 0 188 188 self.time_to_reconnect = None … … 477 477 con.RegisterDisconnectHandler(self._disconnectedReconnCB) 478 478 log.debug(_('Connected to server %s:%s with %s') % (self._current_host['host'], 479 479 self._current_host['port'], con_type)) 480 self._register_handlers(con, con_type)481 480 482 481 name = gajim.config.get_per('accounts', self.name, 'name') 483 482 hostname = gajim.config.get_per('accounts', self.name, 'hostname') … … 487 486 except AttributeError: 488 487 errnum = -1 # we don't have an errnum 489 488 if errnum > 0: 490 # FIXME: tell the user that the certificat is untrusted, and ask him what to do 491 try: 492 log.warning("The authenticity of the "+hostname+" certificate could be invalid.\nSSL Error: "+ssl_error[errnum]) 493 except KeyError: 494 log.warning("Unknown SSL error: %d" % errnum) 489 text = _('The authenticity of the %s certificate could be invalid.') %\ 490 hostname 491 if errnum in ssl_error: 492 text += _('\nSSL Error: %s') % ssl_error[errnum] 493 else: 494 text += _('\nUnknown SSL error: %d') % errnum 495 self.dispatch('SSL_ERROR', (text, con.Connection.ssl_cert_pem, 496 con.Connection.ssl_fingerprint_sha1)) 497 return True 498 if hasattr(con.Connection, 'ssl_fingerprint_sha1'): 499 saved_fingerprint = gajim.config.get_per('accounts', self.name, 'ssl_fingerprint_sha1') 500 if saved_fingerprint: 501 # Check sha1 fingerprint 502 if con.Connection.ssl_fingerprint_sha1 != saved_fingerprint: 503 self.dispatch('FINGERPRINT_ERROR', 504 (con.Connection.ssl_fingerprint_sha1,)) 505 return True 506 self._register_handlers(con, con_type) 495 507 con.auth(name, self.password, self.server_resource, 1, self.__on_auth) 496 508 497 return True498 509 510 def ssl_certificate_accepted(self): 511 name = gajim.config.get_per('accounts', self.name, 'name') 512 self._register_handlers(self.connection, 'ssl') 513 self.connection.auth(name, self.password, self.server_resource, 1, self.__on_auth) 514 499 515 def _register_handlers(self, con, con_type): 500 516 self.peerhost = con.get_peerhost() 501 517 # notify the gui about con_type … … 543 559 544 560 def quit(self, kill_core): 545 561 if kill_core and gajim.account_is_connected(self.name): 546 self.disconnect(on_purpose =True)562 self.disconnect(on_purpose=True) 547 563 548 564 def get_privacy_lists(self): 549 565 if not self.connection:
