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

Rework SSLErrorDialog

parent 07bb750d
<?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 @@ def __init__(self, transient_for, account, cert):
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 @@ def _on_copy_cert_info_button_clicked(self, widget):
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 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.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 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.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 @@ def handle_event_roster_item_exchange(obj):
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