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:
parent
32c4b2ca40
commit
afac304821
1 changed files with 27 additions and 14 deletions
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue