Prefer certifi provided certificates (#108)

Sets the SSL context to use the certifi provided root certificate bundle by default, unless the certifi module is older than a year.

If the system-provided root certificate bundle is empty, certifi certs are always loaded.
This commit is contained in:
Dpeta 2022-12-22 22:03:26 +01:00 committed by GitHub
parent 32c4b2ca40
commit afac304821
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -21,6 +21,7 @@ import ssl
import socket import socket
import select import select
import logging import logging
import datetime
import traceback import traceback
from oyoyo.parse import parse_raw_irc_command from oyoyo.parse import parse_raw_irc_command
@ -207,23 +208,35 @@ class IRCClient:
def get_ssl_context(self): def get_ssl_context(self):
"""Returns an SSL context for connecting over SSL/TLS. """Returns an SSL context for connecting over SSL/TLS.
Loads the certifi certs instead of the system-provided certificates if Loads the certifi root certificate bundle if the certifi module is less
the system certificate store is empty.""" than a year old or if the system certificate store is empty.
context = ssl.create_default_context()
# Check if store is empty The cert store on Windows also seems to have issues, so it's better
empty_cert_store = list(context.cert_store_stats().values()).count(0) == 3 to use the certifi provided bundle assuming it's a recent version.
if empty_cert_store and "certifi" in sys.modules:
# Can't validate certificates if store is empty, On MacOS the system cert store is usually empty, as Python does not use
# load root certificates from certifi instead. the system provided ones, instead relying on a bundle installed with the
context = ssl.create_default_context(cafile=certifi.where()) python installer."""
default_context = ssl.create_default_context()
if "certifi" not in sys.modules:
return default_context
# Get age of certifi module
certifi_date = datetime.datetime.strptime(certifi.__version__, "%Y.%m.%d")
current_date = datetime.datetime.now()
certifi_age = current_date - certifi_date
empty_cert_store = (
list(default_context.cert_store_stats().values()).count(0) == 3
)
# 31557600 seconds is approximately 1 year
if empty_cert_store or certifi_age.total_seconds() <= 31557600:
PchumLog.info( PchumLog.info(
"Using SSL/TLS context with certifi-provided root certificates." "Using SSL/TLS context with certifi-provided root certificates."
) )
else: return ssl.create_default_context(cafile=certifi.where())
PchumLog.info( PchumLog.info("Using SSL/TLS context with system-provided root certificates.")
"Using SSL/TLS context with system-provided root certificates." return default_context
)
return context
def connect(self, verify_hostname=True): def connect(self, verify_hostname=True):
"""initiates the connection to the server set in self.host:self.port """initiates the connection to the server set in self.host:self.port