1# This file is part of Gajim. 2# 3# Gajim is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published 5# by the Free Software Foundation; version 3 only. 6# 7# Gajim is distributed in the hope that it will be useful, 8# but WITHOUT ANY WARRANTY; without even the implied warranty of 9# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10# GNU General Public License for more details. 11# 12# You should have received a copy of the GNU General Public License 13# along with Gajim. If not, see <http://www.gnu.org/licenses/>. 14 15 16import logging 17 18from gi.repository import GLib 19from gi.repository import Gio 20 21from gajim.common import configpaths 22 23from gajim.common.helpers import get_random_string 24from gajim.common.helpers import write_file_async 25 26 27log = logging.getLogger('gajim.c.cert_store') 28 29 30class CertificateStore: 31 def __init__(self): 32 self._path = configpaths.get('CERT_STORE') 33 self._certs = [] 34 35 self._load_certificates() 36 37 def _get_random_path(self): 38 filename = get_random_string() 39 path = self._path / filename 40 if path.exists(): 41 return self._get_random_path() 42 return path 43 44 def _load_certificates(self): 45 for path in self._path.iterdir(): 46 if path.is_dir(): 47 continue 48 try: 49 cert = Gio.TlsCertificate.new_from_file(str(path)) 50 except GLib.Error as error: 51 log.warning('Can\'t load certificate: %s, %s', path, error) 52 continue 53 54 log.info('Loaded: %s', path.stem) 55 self._certs.append(cert) 56 57 log.info('%s Certificates loaded', len(self._certs)) 58 59 def get_certificates(self): 60 return list(self._certs) 61 62 def add_certificate(self, certificate): 63 log.info('Add certificate to trust store') 64 self._certs.append(certificate) 65 pem = certificate.props.certificate_pem 66 path = self._get_random_path() 67 write_file_async(path, 68 pem.encode(), 69 self._on_certificate_write_finished, 70 path) 71 72 def verify(self, certificate, tls_errors): 73 if Gio.TlsCertificateFlags.UNKNOWN_CA in tls_errors: 74 for trusted_certificate in self._certs: 75 if trusted_certificate.is_same(certificate): 76 tls_errors.remove(Gio.TlsCertificateFlags.UNKNOWN_CA) 77 break 78 79 if not tls_errors: 80 return True 81 return False 82 83 @staticmethod 84 def _on_certificate_write_finished(data, error, path): 85 if data is None: 86 log.error('Can\'t store certificate: %s', error) 87 return 88 89 log.info('Certificate stored: %s', path) 90