From b9b7f4fbe56dda07413fba39b1265fdf94de343e Mon Sep 17 00:00:00 2001
From: lovetox <philipp@hoerist.com>
Date: Sun, 5 Apr 2020 18:59:28 +0200
Subject: [PATCH] HTTPUpload: Respect cert store

---
 gajim/common/cert_store.py         | 11 +++++++++++
 gajim/common/client.py             | 10 +++-------
 gajim/common/config.py             |  1 -
 gajim/common/helpers.py            |  6 ++++++
 gajim/common/modules/httpupload.py | 17 ++++++++---------
 5 files changed, 28 insertions(+), 17 deletions(-)

diff --git a/gajim/common/cert_store.py b/gajim/common/cert_store.py
index 95a28fcd6d..3a1b10a7c0 100644
--- a/gajim/common/cert_store.py
+++ b/gajim/common/cert_store.py
@@ -69,6 +69,17 @@ def add_certificate(self, certificate):
                          self._on_certificate_write_finished,
                          path)
 
+    def verify(self, certificate, tls_errors):
+        if Gio.TlsCertificateFlags.UNKNOWN_CA in tls_errors:
+            for trusted_certificate in self._certs:
+                if trusted_certificate.is_same(certificate):
+                    tls_errors.remove(Gio.TlsCertificateFlags.UNKNOWN_CA)
+                    break
+
+        if not tls_errors:
+            return True
+        return False
+
     @staticmethod
     def _on_certificate_write_finished(data, error, path):
         if data is None:
diff --git a/gajim/common/client.py b/gajim/common/client.py
index 99445e70a9..8ed70d4447 100644
--- a/gajim/common/client.py
+++ b/gajim/common/client.py
@@ -21,7 +21,6 @@
 from nbxmpp.const import ConnectionType
 
 from gi.repository import GLib
-from gi.repository import Gio
 
 from gajim.common import passwords
 from gajim.common.nec import NetworkEvent
@@ -36,6 +35,7 @@
 from gajim.common.helpers import get_user_proxy
 from gajim.common.helpers import warn_about_plain_connection
 from gajim.common.helpers import get_resource
+from gajim.common.helpers import get_ignored_ssl_errors
 from gajim.common.i18n import _
 
 from gajim.common.connection_handlers import ConnectionHandlers
@@ -140,7 +140,8 @@ def _create_client(self):
         self._client.set_accepted_certificates(
             app.cert_store.get_certificates())
 
-        self._client.set_ignored_tls_errors(self._get_ignored_ssl_errors())
+        self._client.set_ignored_tls_errors(
+            get_ignored_ssl_errors(self._account))
 
         if app.config.get_per('accounts', self._account,
                               'use_plain_connection'):
@@ -161,11 +162,6 @@ def _create_client(self):
 
         self._register_new_handlers()
 
-    def _get_ignored_ssl_errors(self):
-        ignore_ssl_errors = app.config.get_per(
-            'accounts', self.name, 'ignore_ssl_errors').split()
-        return {Gio.TlsCertificateFlags(int(err)) for err in ignore_ssl_errors}
-
     def process_ssl_errors(self):
         if not self._ssl_errors:
             self.connect(ignore_all_errors=True)
diff --git a/gajim/common/config.py b/gajim/common/config.py
index 99fda10b72..7307b5ba77 100644
--- a/gajim/common/config.py
+++ b/gajim/common/config.py
@@ -346,7 +346,6 @@ class Config:
             'ft_send_local_ips': [opt_bool, True, _('If enabled, Gajim will send your local IP so your contact can connect to your machine for file transfers.')],
             'opened_chat_controls': [opt_str, '', _('List of XMPP Addresses (space separated) for which the chat window will be re-opened on next startup.')],
             'recent_groupchats': [opt_str, ''],
-            'httpupload_verify': [opt_bool, True, _('HTTP File Upload: Enable HTTPS Verification.')],
             'filetransfer_preference' : [opt_str, 'httpupload', _('Preferred file transfer mechanism for file drag&drop on a chat window. Can be \'httpupload\' (default) or \'jingle\'.')],
             'allow_posh': [opt_bool, True, _('Allow certificate verification with POSH.')],
         }, {}),
diff --git a/gajim/common/helpers.py b/gajim/common/helpers.py
index 959802e034..eff9a77e93 100644
--- a/gajim/common/helpers.py
+++ b/gajim/common/helpers.py
@@ -1764,3 +1764,9 @@ def warn_about_plain_connection(account, connection_types):
         if type_.is_plain and warn:
             return True
     return False
+
+
+def get_ignored_ssl_errors(account):
+    ignore_ssl_errors = app.config.get_per(
+        'accounts', account, 'ignore_ssl_errors').split()
+    return {Gio.TlsCertificateFlags(int(err)) for err in ignore_ssl_errors}
diff --git a/gajim/common/modules/httpupload.py b/gajim/common/modules/httpupload.py
index 4206f95335..66ae6aad60 100644
--- a/gajim/common/modules/httpupload.py
+++ b/gajim/common/modules/httpupload.py
@@ -22,6 +22,7 @@
 
 from nbxmpp import NS_HTTPUPLOAD_0
 from nbxmpp.util import is_error_result
+from nbxmpp.util import convert_tls_error_flags
 from gi.repository import GLib
 from gi.repository import Soup
 
@@ -218,23 +219,21 @@ def _upload_file(self, transfer):
         self._session.queue_message(message, self._on_finish, transfer)
 
     def _check_certificate(self, message):
-        https_used, _tls_certificate, tls_errors = message.get_https_status()
+        https_used, tls_certificate, tls_errors = message.get_https_status()
         if not https_used:
             self._log.warning('HTTPS was not used for upload')
             self._session.cancel_message(message, Soup.Status.CANCELLED)
             return
 
-        if not app.config.get_per('accounts',
-                                  self._account,
-                                  'httpupload_verify'):
+        tls_errors = convert_tls_error_flags(tls_errors)
+        if app.cert_store.verify(tls_certificate, tls_errors):
             return
 
-        if tls_errors:
-            phrase = get_tls_error_phrase(tls_errors)
+        for error in tls_errors:
+            phrase = get_tls_error_phrase(error)
             self._log.warning('TLS verification failed: %s', phrase)
-            self._session.cancel_message(message, Soup.Status.CANCELLED)
-            self._raise_information_event('httpupload-error', phrase)
-            return
+        self._session.cancel_message(message, Soup.Status.CANCELLED)
+        self._raise_information_event('httpupload-error', phrase)
 
     def _on_finish(self, _session, message, transfer):
         self._queued_messages.pop(id(transfer), None)
-- 
GitLab