Validate certificates when using SSL/TLS

This commit is contained in:
Dpeta 2022-09-02 05:34:37 +02:00
parent a3d047350b
commit a906b6a98e
5 changed files with 49 additions and 10 deletions

View file

@ -5,6 +5,11 @@
### Added
- Support for color via IRCv3 metadata draft.
- Prompt for connecting anyway when certificate validation fails.
### Changed
- Reenabled server certificate validation when using SSL.
- Uses the system's local certificates, so might fail on some installations.
### Fixed
- Error when setting quirk with PyQt5.

View file

@ -14,4 +14,4 @@
- Console is hopelessly broken, it'd be easier to make a list of what commands *don't* cause it to crash. Does anyone use this?
## CHANGE
- When everything has been tested and more people have compatible versions, switch Pesterchum over to using metadata and message tags by default instead of wraping its protocol in PRIVMSG. The current method should stay availible for compatibility.
- When everything has been tested and more people have compatible versions, switch Pesterchum over to using metadata and message tags by default instead of wrapping its protocol in PRIVMSG. The current method should stay available for compatibility.

12
irc.py
View file

@ -4,6 +4,7 @@ import socket
import random
import time
import json
import ssl
try:
from PyQt6 import QtCore, QtGui
@ -40,12 +41,13 @@ QString = str
# logging.basicConfig(level=logging.WARNING)
class PesterIRC(QtCore.QThread):
def __init__(self, config, window):
def __init__(self, config, window, verify_hostname=True):
QtCore.QThread.__init__(self)
self.mainwindow = window
self.config = config
self.unresponsive = False
self.registeredIRC = False
self.verify_hostname = verify_hostname
self.metadata_supported = False
self.stopIRC = None
self.NickServ = services.NickServ()
@ -61,7 +63,12 @@ class PesterIRC(QtCore.QThread):
timeout=120)
self.cli.command_handler.parent = self
self.cli.command_handler.mainwindow = self.mainwindow
self.cli.connect()
try:
self.cli.connect(self.verify_hostname)
except ssl.SSLCertVerificationError as e:
# Ask if users wants to connect anyway
self.askToConnect.emit(e)
raise e
self.conn = self.cli.conn()
def run(self):
try:
@ -395,6 +402,7 @@ class PesterIRC(QtCore.QThread):
chanInviteOnly = QtCore.pyqtSignal('QString')
modesUpdated = QtCore.pyqtSignal('QString', 'QString')
connected = QtCore.pyqtSignal()
askToConnect = QtCore.pyqtSignal(Exception)
userPresentUpdate = QtCore.pyqtSignal('QString', 'QString',
'QString')
cannotSendToChan = QtCore.pyqtSignal('QString', 'QString')

View file

@ -185,14 +185,14 @@ class IRCClient:
#raise se
self._end = True # This ok?
def connect(self):
def connect(self, verify_hostname=True):
""" initiates the connection to the server set in self.host:self.port
"""
PchumLog.info('connecting to %s:%s' % (self.host, self.port))
if self.ssl == True:
context = ssl.create_default_context()
# Checking relies on the system
if verify_hostname == False:
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
@ -208,6 +208,11 @@ class IRCClient:
select.select([self.socket], [], [])
except ssl.SSLWantWriteError:
select.select([], [self.socket], [])
except ssl.SSLCertVerificationError as e:
# Disconnect for now
self.socket.close()
bare_sock.close()
raise e
PchumLog.info("secure sockets version is %s" % self.socket.version())

View file

@ -3694,6 +3694,26 @@ class PesterWindow(MovingWindow):
self.chooseServerWidged.show()
self.chooseServerWidged.setFocus()
@QtCore.pyqtSlot(Exception)
def connectAnyway(self, e):
# Prompt user to connect anyway
msgbox = QtWidgets.QMessageBox()
msgbox.setStyleSheet("QMessageBox{ %s }"
% self.theme["main/defaultwindow/style"])
msgbox.setIcon(QtWidgets.QMessageBox.Icon.Warning)
msgbox.setText("Server certificate validation failed")
msgbox.setInformativeText("Reason: \"%s (%s)\"" % (e.verify_message, e.verify_code)
+ "\n\nConnect anyway?")
msgbox.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Yes
| QtWidgets.QMessageBox.StandardButton.No)
msgbox.setDefaultButton(QtWidgets.QMessageBox.StandardButton.No)
ret = msgbox.exec()
if ret == QtWidgets.QMessageBox.StandardButton.Yes:
self.parent.restartIRC(verify_hostname=False)
else:
return False
pcUpdate = QtCore.pyqtSignal('QString', 'QString')
closeToTraySignal = QtCore.pyqtSignal()
newConvoStarted = QtCore.pyqtSignal('QString', bool, name="newConvoStarted")
@ -3982,6 +4002,7 @@ class MainProgram(QtCore.QObject):
(widget.disconnectIRC, irc.disconnectIRC),
# Main window --> IRC
(irc.connected, widget.connected),
(irc.askToConnect, widget.connectAnyway),
(irc.moodUpdated, widget.updateMoodSlot),
(irc.colorUpdated, widget.updateColorSlot),
(irc.messageReceived, widget.deliverMessage),
@ -4069,7 +4090,7 @@ class MainProgram(QtCore.QObject):
else:
self.restartIRC()
@QtCore.pyqtSlot()
def restartIRC(self):
def restartIRC(self, verify_hostname=True):
if hasattr(self, 'irc') and self.irc:
self.disconnectWidgets(self.irc, self.widget)
stop = self.irc.stopIRC
@ -4077,7 +4098,7 @@ class MainProgram(QtCore.QObject):
else:
stop = None
if stop is None:
self.irc = PesterIRC(self.widget.config, self.widget)
self.irc = PesterIRC(self.widget.config, self.widget, verify_hostname=verify_hostname)
self.connectWidgets(self.irc, self.widget)
self.irc.start()
if self.attempts == 1: