Compare commits

...

7 Commits

Author SHA1 Message Date
Safihre
e93e01dd59 Update text files for 4.4.1 2024-12-20 11:16:01 +01:00
Safihre
79b504ff93 Update text files for 4.4.1RC1 2024-12-18 13:17:47 +01:00
Safihre
52dafd4ab8 Add new Certificate verification setting Medium
Closes #2993
2024-12-18 12:53:59 +01:00
Safihre
0cc538ac5a Don't block virusscanner certificates on Windows
See #2993
2024-12-14 21:52:47 +01:00
Safihre
4b99d04454 Add missing hidden import for Windows notifications 2024-12-13 15:00:19 +01:00
Safihre
07be38cd01 Update text files for 4.4.0 2024-12-09 21:55:33 +01:00
Safihre
0121e0ae16 Update release date of 4.4.0 in appdata 2024-12-09 21:50:07 +01:00
14 changed files with 85 additions and 29 deletions

View File

@@ -69,14 +69,14 @@ jobs:
# We need the official Python, because the GA ones only support newer macOS versions
# The deployment target is picked up by the Python build tools automatically
# If updated, make sure to also set LSMinimumSystemVersion in SABnzbd.spec
PYTHON_VERSION: "3.13.0"
PYTHON_VERSION: "3.13.1"
MACOSX_DEPLOYMENT_TARGET: "10.13"
# We need to force compile for universal2 support
CFLAGS: -arch x86_64 -arch arm64
ARCHFLAGS: -arch x86_64 -arch arm64
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.13.0
- name: Set up Python 3.13
# Only use this for the caching of pip packages!
uses: actions/setup-python@v5
with:

View File

@@ -1,9 +1,12 @@
Release Notes - SABnzbd 4.4.0 Release Candidate 1
Release Notes - SABnzbd 4.4.1
=========================================================
This is the first release candidate of SABnzbd 4.4.0.
## Bugfixes and changes since 4.4.0
* Added `Certificate verification` level `Medium` to allow
certificates injected by firewall or virus scanner.
* Windows: Windows notifications did not work.
## New features since 4.3.0
## New features in 4.4.0
* Subtitle files will be deobfuscated if required.
* Show server `Personal notes` on the main servers display.
@@ -12,7 +15,7 @@ This is the first release candidate of SABnzbd 4.4.0.
* macOS and Windows: Use Python 3.13 for release.
* Windows: The next release will no longer support Windows 32bit or Windows 7.
## Bug fixes since 4.3.0
## Bug fixes in 4.4.0
* Toggling of Servers could result in jobs being stuck at 99%.
* Corrupt NZB's could also result in jobs being stuck at 99%.

View File

@@ -40,7 +40,7 @@ else:
)
# Windows
extra_hiddenimports.extend(["win32timezone"])
extra_hiddenimports.extend(["win32timezone", "winrt.windows.foundation.collections"])
EXTRA_FOLDERS += ["win/multipar/", "win/par2/", "win/unrar/", "win/7zip/"]
EXTRA_FILES += ["portable.cmd"]

View File

@@ -94,11 +94,12 @@
<div class="field-pair advanced-settings">
<label class="config" for="ssl_verify">$T('opt-ssl_verify')</label>
<select name="ssl_verify" id="ssl_verify">
<option value="2" selected>$T('ssl_verify-strict')</option>
<option value="1">$T('ssl_verify-normal')</option>
<option value="3" selected>$T('ssl_verify-strict')</option>
<option value="2">$T('ssl_verify-medium')</option>
<option value="1">$T('ssl_verify-minimal')</option>
<option value="0">$T('ssl_verify-disabled')</option>
</select>
<span class="desc">$T('explain-ssl_verify').replace('. ', '.<br/>')</span>
<span class="desc">$T('explain-ssl_verify').replace('-', '<br/>-')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="ssl_ciphers">$T('opt-ssl_ciphers')</label>
@@ -224,11 +225,12 @@
<div class="field-pair advanced-settings">
<label class="config" for="ssl_verify$cur">$T('opt-ssl_verify')</label>
<select name="ssl_verify" id="ssl_verify$cur">
<option value="2" <!--#if $server['ssl_verify'] == 2 then 'selected="selected"' else ""#--> >$T('ssl_verify-strict')</option>
<option value="1" <!--#if $server['ssl_verify'] == 1 then 'selected="selected"' else ""#--> >$T('ssl_verify-normal')</option>
<option value="3" <!--#if $server['ssl_verify'] == 3 then 'selected="selected"' else ""#--> >$T('ssl_verify-strict')</option>
<option value="2" <!--#if $server['ssl_verify'] == 2 then 'selected="selected"' else ""#--> >$T('ssl_verify-medium')</option>
<option value="1" <!--#if $server['ssl_verify'] == 1 then 'selected="selected"' else ""#--> >$T('ssl_verify-minimal')</option>
<option value="0" <!--#if $server['ssl_verify'] == 0 then 'selected="selected"' else ""#--> >$T('ssl_verify-disabled')</option>
</select>
<span class="desc">$T('explain-ssl_verify').replace('. ', '.<br/>')</span>
<span class="desc">$T('explain-ssl_verify').replace('-', '<br/>-')</span>
</div>
<div class="field-pair advanced-settings">
<label class="config" for="ssl_ciphers$cur">$T('opt-ssl_ciphers')</label>

View File

@@ -70,10 +70,12 @@
<label for="ssl_verify" class="col-sm-4 control-label">$T('opt-ssl_verify')</label>
<div class="col-sm-8">
<select name="ssl_verify" id="ssl_verify" class="form-control">
<option value="2" <!--#if $ssl_verify == 2 then 'selected="selected"' else ""#--> >$T('ssl_verify-strict')</option>
<option value="1" <!--#if $ssl_verify == 1 then 'selected="selected"' else ""#--> >$T('ssl_verify-normal')</option>
<option value="3" <!--#if $ssl_verify == 3 then 'selected="selected"' else ""#--> >$T('ssl_verify-strict')</option>
<option value="2" <!--#if $ssl_verify == 2 then 'selected="selected"' else ""#--> >$T('ssl_verify-medium')</option>
<option value="1" <!--#if $ssl_verify == 1 then 'selected="selected"' else ""#--> >$T('ssl_verify-minimal')</option>
<option value="0" <!--#if $ssl_verify == 0 then 'selected="selected"' else ""#--> >$T('ssl_verify-disabled')</option>
</select>
<span class="desc">$T('explain-ssl_verify').replace('-', '<br/>-')</span>
</div>
</div>
</div>

View File

@@ -88,6 +88,10 @@ label {
float: right;
margin: 0;
}
.desc {
font-size: 12px;
font-style: italic;
}
.align-right {
text-align: right;
}

View File

@@ -30,7 +30,8 @@
<url type="faq">https://sabnzbd.org/wiki/faq</url>
<url type="contact">https://sabnzbd.org/live-chat.html</url>
<releases>
<release version="4.4.0" date="2024-12-14" type="stable"/>
<release version="4.4.1" date="2024-12-23" type="stable"/>
<release version="4.4.0" date="2024-12-09" type="stable"/>
<release version="4.3.3" date="2024-08-01" type="stable"/>
<release version="4.3.2" date="2024-05-30" type="stable"/>
<release version="4.3.1" date="2024-05-03" type="stable"/>

View File

@@ -1270,7 +1270,7 @@ def test_nntp_server_dict(kwargs: Dict[str, Union[str, List[str]]]) -> Tuple[boo
connections = int_conv(kwargs.get("connections", 0))
timeout = int_conv(kwargs.get("timeout", DEF_NETWORKING_TEST_TIMEOUT))
ssl = int_conv(kwargs.get("ssl", 0))
ssl_verify = int_conv(kwargs.get("ssl_verify", 1))
ssl_verify = int_conv(kwargs.get("ssl_verify", 3))
ssl_ciphers = kwargs.get("ssl_ciphers", "").strip()
if not host:

View File

@@ -36,6 +36,8 @@ from sabnzbd.config import (
OptionStr,
OptionList,
create_api_key,
get_servers,
save_config,
)
from sabnzbd.constants import (
DEF_HOST,
@@ -799,3 +801,18 @@ def config_conversions():
# Done
config_conversion_version.set(3)
# Convert Certificate Validation
if config_conversion_version() < 4:
logging.info("Config conversion set 4")
all_servers = get_servers()
for server in all_servers:
if all_servers[server].ssl_verify() == 2:
all_servers[server].ssl_verify.set(3)
# Done
config_conversion_version.set(4)
# Make sure we store the new values
save_config()

View File

@@ -438,8 +438,8 @@ class ConfigServer:
self.password = OptionPassword(name, "password", add=False)
self.connections = OptionNumber(name, "connections", 1, 0, 500, add=False)
self.ssl = OptionBool(name, "ssl", False, add=False)
# 0=No, 1=Normal, 2=Strict (hostname verification)
self.ssl_verify = OptionNumber(name, "ssl_verify", 2, add=False)
# 0=No, 1=Minimal, 2=Medium, 3=Strict
self.ssl_verify = OptionNumber(name, "ssl_verify", 3, add=False)
self.ssl_ciphers = OptionStr(name, "ssl_ciphers", add=False)
self.enable = OptionBool(name, "enable", True, add=False)
self.required = OptionBool(name, "required", False, add=False)

View File

@@ -77,10 +77,15 @@ def internetspeed_worker(secure_sock: ssl.SSLSocket, socket_speed: Dict[ssl.SSLS
def internetspeed_interal(family: int = socket.AF_UNSPEC) -> float:
"""Measure internet speed from a test-download using our optimized SSL-code"""
context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
socket_speed = {}
# Allow those pesky virus-scanners to inject their scanning certificates
# This is enabled by default because it's just a speedtest anyway
if hasattr(ssl, "VERIFY_X509_PARTIAL_CHAIN"):
context.verify_flags &= ~ssl.VERIFY_X509_PARTIAL_CHAIN
context.verify_flags &= ~ssl.VERIFY_X509_STRICT
try:
if not (addrinfo := happyeyeballs(TEST_HOSTNAME, TEST_PORT, DEF_NETWORKING_SHORT_TIMEOUT, family)):
# no addrinfo from happyeyeballs, so no connection was possible

View File

@@ -283,14 +283,29 @@ class NNTP:
# Create SSL-context if it is needed and not created yet
if self.nw.server.ssl and not self.nw.server.ssl_context:
# Setup the SSL socket
# Set Certificate validation: 0=Disabled, 1=Minimal, 2=Medium, 3=Strict
self.nw.server.ssl_context = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
# Only verify hostname when we're strict
if self.nw.server.ssl_verify < 2:
# Allow those pesky virus-scanners to inject their scanning certificates
if self.nw.server.ssl_verify <= 2:
self.nw.server.ssl_context.verify_flags &= ~ssl.VERIFY_X509_STRICT
# This flag is only available for Python 3.10 and above
if hasattr(ssl, "VERIFY_X509_PARTIAL_CHAIN"):
self.nw.server.ssl_context.verify_flags &= ~ssl.VERIFY_X509_PARTIAL_CHAIN
else:
# Make sure it's enabled for Strict mode, also pre-3.13
self.nw.server.ssl_context.verify_flags |= ssl.VERIFY_X509_STRICT
# This flag is only available for Python 3.10 and above
if hasattr(ssl, "VERIFY_X509_PARTIAL_CHAIN"):
self.nw.server.ssl_context.verify_flags |= ssl.VERIFY_X509_PARTIAL_CHAIN
# Only verify hostname when Medium or Strict
if self.nw.server.ssl_verify <= 1:
self.nw.server.ssl_context.check_hostname = False
# Certificates optional
if self.nw.server.ssl_verify == 0:
self.nw.server.ssl_context.verify_mode = ssl.CERT_NONE
# Certificates optional
if self.nw.server.ssl_verify <= 0:
self.nw.server.ssl_context.verify_mode = ssl.CERT_NONE
# Did the user set a custom cipher-string?
if self.nw.server.ssl_ciphers:
@@ -370,7 +385,9 @@ class NNTP:
"Certificate hostname mismatch: the server hostname is not listed in the certificate. This is a server issue."
)
elif "certificate verify failed" in raw_error_str:
raw_error_str = T("Certificate not valid. This is most probably a server issue.")
raw_error_str = T(
"Certificate could not be validated. This could be a server issue or due to a locally injected certificate (for example by firewall or virus scanner). Try setting Certificate verification to Medium."
)
# Reformat error and overwrite str-representation
error_str = T("Server %s uses an untrusted certificate [%s]") % (self.nw.server.host, raw_error_str)

View File

@@ -550,10 +550,15 @@ SKIN_TEXT = {
"explain-ssl": TT("Secure connection to server"), #: Server SSL tickbox
"opt-ssl_verify": TT("Certificate verification"),
"explain-ssl_verify": TT(
"Minimal: when SSL is enabled, verify the identity of the server using its certificates. Strict: verify and enforce matching hostname."
"When SSL is enabled: "
"- Strict: enforce full certificate verification. This is the most secure setting. "
"- Medium: verify that the certificate is valid and matches the server address, but allow certificates locally injected (for example by firewall or virus scanner)."
"- Minimal: verify that the certificate is valid. This is not secure, any valid certificate could be used. "
"- Disabled: no certification verification. This is not secure at all, anyone could intercept your connection. "
),
"ssl_verify-disabled": TT("Disabled"),
"ssl_verify-normal": TT("Minimal"),
"ssl_verify-minimal": TT("Minimal"),
"ssl_verify-medium": TT("Medium"),
"ssl_verify-strict": TT("Strict"),
"srv-priority": TT("Priority"), #: Server priority
"explain-svrprio": TT("0 is highest priority, 100 is the lowest priority"), #: Explain server priority

View File

@@ -6,5 +6,5 @@
# You MUST use double quotes (so " and not ')
# Do not forget to update the appdata file for every major release!
__version__ = "4.4.0RC1"
__version__ = "4.4.1"
__baseline__ = "unknown"