Commit ac428f11 authored by Daniel Brötzmann's avatar Daniel Brötzmann Committed by Philipp Hörist

Rework SSLErrorDialog

parent 07bb750d
Pipeline #4222 passed with stages
in 2 minutes and 43 seconds
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.20"/>
<object class="GtkBox" id="ssl_error_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="border_width">18</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">6</property>
<property name="label" translatable="yes">SSL Certificate Verification Error</property>
<style>
<class name="large-header"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="intro_text">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_right">30</property>
<property name="margin_bottom">6</property>
<property name="wrap">True</property>
<property name="max_width_chars">50</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Identified Error</property>
<style>
<class name="bold"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="ssl_error">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_bottom">12</property>
<property name="label" translatable="yes">&lt;error&gt;</property>
<property name="wrap">True</property>
<property name="max_width_chars">42</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="add_certificate_checkbutton">
<property name="label" translatable="yes">Add this certificate to the list of _trusted certificates</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="no_show_all">True</property>
<property name="halign">start</property>
<property name="margin_left">15</property>
<property name="margin_right">15</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">4</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="ignore_error_checkbutton">
<property name="label" translatable="yes">_Ignore this error for this certificate</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="margin_left">15</property>
<property name="margin_right">15</property>
<property name="use_underline">True</property>
<property name="draw_indicator">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">5</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">12</property>
<property name="spacing">12</property>
<child>
<object class="GtkButton" id="abort_button">
<property name="label" translatable="yes">_Abort</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="_on_abort_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="view_cert_button">
<property name="label" translatable="yes">_View Certificate</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="halign">center</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="_on_view_cert_clicked" swapped="no"/>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="connect_button">
<property name="label" translatable="yes">_Connect</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="hexpand">True</property>
<property name="use_underline">True</property>
<signal name="clicked" handler="_on_connect_clicked" swapped="no"/>
<style>
<class name="destructive-action"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">6</property>
</packing>
</child>
</object>
</interface>
......@@ -13,7 +13,6 @@
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime
from collections import namedtuple
from gi.repository import GLib
......@@ -536,6 +535,7 @@ class CertificateDialog(Gtk.ApplicationWindow):
self.set_resizable(False)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_title(_('Certificate'))
self.account = account
self._ui = get_builder('certificate_dialog.ui')
self.add(self._ui.certificate_box)
......@@ -603,25 +603,6 @@ class CertificateDialog(Gtk.ApplicationWindow):
self._clipboard.set_text(clipboard_text, -1)
class SSLErrorDialog(ConfirmationDialogDoubleCheck):
def __init__(self, account, certificate, pritext, sectext, checktext1,
checktext2, on_response_ok=None, on_response_cancel=None):
self.account = account
self.cert = certificate
ConfirmationDialogDoubleCheck.__init__(
self, pritext, sectext,
checktext1, checktext2, on_response_ok=on_response_ok,
on_response_cancel=on_response_cancel, is_modal=False)
b = Gtk.Button(_('View certificate…'))
b.connect('clicked', self.on_cert_clicked)
b.show_all()
area = self.get_action_area()
area.pack_start(b, True, True, 0)
def on_cert_clicked(self, button):
CertificateDialog(self, self.account, self.cert)
class ChangePasswordDialog(Gtk.Dialog):
def __init__(self, account, success_cb, transient_for):
super().__init__(title=_('Change Password'),
......
# This file is part of Gajim.
#
# Gajim is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 3 only.
#
# Gajim is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Gajim. If not, see <http://www.gnu.org/licenses/>.
import os
from OpenSSL import crypto
from gi.repository import Gtk
from gajim.common import app
from gajim.common import configpaths
from gajim.common.const import SSLError
from gajim.common.connection_handlers_events import OurShowEvent
from gajim.common.i18n import _
from gajim.gtk.dialogs import CertificateDialog
from gajim.gtk.util import get_builder
class SSLErrorDialog(Gtk.ApplicationWindow):
def __init__(self, account, connection, cert, error_num):
Gtk.ApplicationWindow.__init__(self)
self.set_name('SSLErrorDialog')
self.set_application(app.app)
self.set_show_menubar(False)
self.set_resizable(False)
self.set_position(Gtk.WindowPosition.CENTER)
self.set_title(_('SSL Certificate Verification Error'))
self._ui = get_builder('ssl_error_dialog.ui')
self.add(self._ui.ssl_error_box)
self.account = account
self._error_num = error_num
self._con = connection
self._cert = cert
self._server = app.config.get_per('accounts', self.account, 'hostname')
self._process_error()
self._ui.connect_signals(self)
self.show_all()
def _process_error(self):
self._ui.intro_text.set_text(
_('There was an error while attempting to verify the SSL '
'certificate of your XMPP server (%s).') % self._server)
unknown_error = _('Unknown SSL error \'%s\'') % self._error_num
ssl_error = SSLError.get(self._error_num, unknown_error)
self._ui.ssl_error.set_text(ssl_error)
if self._error_num in (18, 27):
# Errors: 18 Self signed certificate; 27 Certificate not trusted
self._ui.add_certificate_checkbutton.show()
def _on_abort_clicked(self, _button):
self._con.disconnect(reconnect=False)
app.nec.push_incoming_event(OurShowEvent(None, conn=self._con,
show='offline'))
self.destroy()
def _on_view_cert_clicked(self, _button):
window = app.get_app_window(CertificateDialog, self.account)
if window is None:
CertificateDialog(self, self.account, self._cert)
else:
window.present()
def _on_connect_clicked(self, _button):
# Ignore this error
if self._ui.ignore_error_checkbutton.get_active():
ignore_ssl_errors = app.config.get_per(
'accounts', self.account, 'ignore_ssl_errors').split()
ignore_ssl_errors.append(str(self._error_num))
app.config.set_per('accounts', self.account, 'ignore_ssl_errors',
' '.join(ignore_ssl_errors))
if self._ui.add_certificate_checkbutton.get_active():
pem = crypto.dump_certificate(
crypto.FILETYPE_PEM, self._cert).decode('utf-8')
# Check if cert is already in file
certs = ''
my_ca_certs = configpaths.get('MY_CACERTS')
if os.path.isfile(my_ca_certs):
with open(my_ca_certs, encoding='utf-8') as f:
certs = f.read()
if pem not in certs:
with open(my_ca_certs, 'a', encoding='utf-8') as f:
f.write(self._server + '\n')
f.write(pem + '\n\n')
self._con.process_ssl_errors()
self.destroy()
......@@ -46,7 +46,6 @@ from gi.repository import Gio
from nbxmpp import idlequeue
from nbxmpp import Hashes2
from nbxmpp.structs import TuneData
import OpenSSL
from gajim.common import app
from gajim.common import events
......@@ -86,7 +85,6 @@ from gajim.common.connection_handlers_events import (
from gajim.common.modules.httpupload import HTTPUploadProgressEvent
from gajim.common.connection import Connection
from gajim.common.file_props import FilesProp
from gajim.common.const import SSLError
from gajim import roster_window
from gajim.common import ged
......@@ -103,7 +101,6 @@ from gajim.gtk.dialogs import NewConfirmationCheckDialog
from gajim.gtk.dialogs import DialogButton
from gajim.gtk.dialogs import InputDialog
from gajim.gtk.dialogs import PassphraseDialog
from gajim.gtk.dialogs import SSLErrorDialog
from gajim.gtk.dialogs import InvitationReceivedDialog
from gajim.gtk.profile import ProfileWindow
from gajim.gtk.filechoosers import FileChooserDialog
......@@ -113,6 +110,7 @@ from gajim.gtk.filetransfer import FileTransfersWindow
from gajim.gtk.http_upload_progress import HTTPUploadProgressWindow
from gajim.gtk.roster_item_exchange import RosterItemExchangeWindow
from gajim.gtk.subscription_request import SubscriptionRequestWindow
from gajim.gtk.ssl_error_dialog import SSLErrorDialog
from gajim.gtk.util import get_show_in_roster
from gajim.gtk.util import get_show_in_systray
......@@ -1090,74 +1088,15 @@ class Interface:
def handle_event_ssl_error(self, obj):
account = obj.conn.name
server = app.config.get_per('accounts', account, 'hostname')
def on_ok(is_checked):
del self.instances[account]['online_dialog']['ssl_error']
if is_checked[0]:
pem = OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_PEM, obj.cert).decode('utf-8')
# Check if cert is already in file
certs = ''
my_ca_certs = configpaths.get('MY_CACERTS')
if os.path.isfile(my_ca_certs):
with open(my_ca_certs, encoding='utf-8') as f:
certs = f.read()
if pem in certs:
ErrorDialog(_('Certificate Already in File'),
_('This certificate is already in file %s, so it\'s '
'not added again.') % my_ca_certs)
else:
with open(my_ca_certs, 'a', encoding='utf-8') as f:
f.write(server + '\n')
f.write(pem + '\n\n')
if is_checked[1]:
ignore_ssl_errors = app.config.get_per('accounts', account,
'ignore_ssl_errors').split()
ignore_ssl_errors.append(str(obj.error_num))
app.config.set_per('accounts', account, 'ignore_ssl_errors',
' '.join(ignore_ssl_errors))
obj.conn.process_ssl_errors()
connection = obj.conn
cert = obj.cert
error_num = obj.error_num
def on_cancel():
del self.instances[account]['online_dialog']['ssl_error']
obj.conn.disconnect(reconnect=False)
app.nec.push_incoming_event(OurShowEvent(None, conn=obj.conn,
show='offline'))
text = _('The authenticity of the %s '
'certificate could be invalid') % server
default_text = _('\nUnknown SSL error: %d') % obj.error_num
ssl_error_text = SSLError.get(obj.error_num, default_text)
text += _('\nSSL Error: <b>%s</b>') % ssl_error_text
fingerprint_sha1 = obj.cert.digest('sha1').decode('utf-8')
fingerprint_sha256 = obj.cert.digest('sha256').decode('utf-8')
pritext = _('Error verifying SSL certificate')
sectext = _('There was an error verifying the SSL certificate of your '
'XMPP server: %(error)s\nDo you still want to connect to this '
'server?') % {'error': text}
if obj.error_num in (18, 27):
checktext1 = _('Add this certificate to the list of trusted '
'certificates.\nSHA-1 fingerprint of the certificate:\n%(sha1)s'
'\nSHA-256 fingerprint of the certificate:\n%(sha256)s') % \
{'sha1': fingerprint_sha1, 'sha256': fingerprint_sha256}
window = app.get_app_window(SSLErrorDialog, account)
if window is None:
SSLErrorDialog(account, connection, cert, error_num)
else:
checktext1 = ''
checktext2 = _('Ignore this error for this certificate.')
if 'ssl_error' in self.instances[account]['online_dialog']:
self.instances[account]['online_dialog']['ssl_error'].destroy()
self.instances[account]['online_dialog']['ssl_error'] = \
SSLErrorDialog(obj.conn.name, obj.cert, pritext,
sectext, checktext1, checktext2, on_response_ok=on_ok,
on_response_cancel=on_cancel)
self.instances[account]['online_dialog']['ssl_error'].set_title(
_('SSL Certificate Verification for %s') % account)
window.present()
def handle_event_plain_connection(self, obj):
# ('PLAIN_CONNECTION', account, (connection))
......
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import OpenSSL
from test.gtk import util
from gajim.common.const import CSSPriority
from gajim.gtk.ssl_error_dialog import SSLErrorDialog
util.load_style('gajim.css', CSSPriority.APPLICATION)
cert = '''
-----BEGIN CERTIFICATE-----
MIIFhDCCBGygAwIBAgISA4oUEifTr7Y+mcdiwu6KWpcVMA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
ExpMZXQncyBFbmNyeXB0IEF1dGhvcml0eSBYMzAeFw0xOTA0MDMxODE3NDVaFw0x
OTA3MDIxODE3NDVaMBsxGTAXBgNVBAMMECoubGlnaHR3aXRjaC5vcmcwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC/3mcevikse7QwDYwPcGAD9zHw3UWE
7J8SJR349/rFTF2tBFDvEa62OUKTCg5vPKVKaXHlzruk/A7blgqsEdugycORwPD1
7YNJ27EldrRtotjclurzKL6D/MgcaQ4cTkPOD3cWbf/L+HClGrpFt7su6Z6cTutC
wiAYAdlfmVgSSv15F1xOTyFyfGJKQnW628Xs8xUvZh5H/SsEEum4MwVVGW06Z/A/
mwX2jmJUb2M25S1Ma025nZpGYyAAqecTmPb3fStnXm4sdytfZhm4+nj9mH9GQIU1
t/jO/7X7IFpc9DvVRSumSVqvNaVgiWmTLP4VxlCVJO6mibOXXUUDA5RfAgMBAAGj
ggKRMIICjTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsG
AQUFBwMCMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFC4/ZRurw2wVFsgJBTb9Fh/3
0aV9MB8GA1UdIwQYMBaAFKhKamMEfd265tE5t6ZFZe/zqOyhMG8GCCsGAQUFBwEB
BGMwYTAuBggrBgEFBQcwAYYiaHR0cDovL29jc3AuaW50LXgzLmxldHNlbmNyeXB0
Lm9yZzAvBggrBgEFBQcwAoYjaHR0cDovL2NlcnQuaW50LXgzLmxldHNlbmNyeXB0
Lm9yZy8wSQYDVR0RBEIwQIIQKi5saWdodHdpdGNoLm9yZ4IOKi5tZXRyb25vbWUu
aW2CDmxpZ2h0d2l0Y2gub3JnggxtZXRyb25vbWUuaW0wTAYDVR0gBEUwQzAIBgZn
gQwBAgEwNwYLKwYBBAGC3xMBAQEwKDAmBggrBgEFBQcCARYaaHR0cDovL2Nwcy5s
ZXRzZW5jcnlwdC5vcmcwggECBgorBgEEAdZ5AgQCBIHzBIHwAO4AdQB0ftqDMa0z
EJEhnM4lT0Jwwr/9XkIgCMY3NXnmEHvMVgAAAWnkosBAAAAEAwBGMEQCICEfmTBk
OxS95eiYsfTH5HdL7kfp68BSin5LqeGyyxk9AiA3qeDZNKklJTdWqYjto7kUqJNd
YiL99SrqwzR6w+AqSwB1ACk8UZZUyDlluqpQ/FgH1Ldvv1h6KXLcpMMM9OVFR/R4
AAABaeSiwEUAAAQDAEYwRAIgFxouOkJeqkQUe6zNI5w/6YBIQFrsrIZdPcX+r6JI
is8CIEEETzlEyj9lWR/BSSruSp0FT5CuoNNeEG7HxrJ+gVhZMA0GCSqGSIb3DQEB
CwUAA4IBAQAQtfs1NPNMmBQRcKsZyGLZsvpp2hIhdYi72RYnHnIl4MXbhyNj9xtI
cJr9PQ+3FsSnxy7LDjZMpbmBuXhawOyPBPw2M0f0Tv6Eo6miwvP/X1kLE3VjTzCo
6JPh6bEB5wa+kH/pUcGlV6uyT7IuXOiArx0VmIpTA3uwlVdfynOnR3CF20Ds4FLc
JxbGMqRuw/sGiTLKlXc1xVil8WZjL3hokzrgI7K6np2skUjWuMZvhJgwi5QiE7/C
ejsJoYkpvcaiaLAyVymTY/n/oM2oQpv5Mqjit+18RB9c2P+ifH5iDKC/jTKn4NNz
8xSTlUlCBTCozjzscZVeVDIojmejWclT
-----END CERTIFICATE-----'''
cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
ssl_error_num = 10
win = SSLErrorDialog('testacc', None, cert, ssl_error_num)
win.connect('destroy', Gtk.main_quit)
win.show_all()
Gtk.main()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment