mirror of
https://github.com/sabnzbd/sabnzbd.git
synced 2025-12-24 16:19:31 -05:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e93e01dd59 | ||
|
|
79b504ff93 | ||
|
|
52dafd4ab8 | ||
|
|
0cc538ac5a | ||
|
|
4b99d04454 | ||
|
|
07be38cd01 | ||
|
|
0121e0ae16 |
4
.github/workflows/build_release.yml
vendored
4
.github/workflows/build_release.yml
vendored
@@ -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:
|
||||
|
||||
11
README.mkd
11
README.mkd
@@ -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%.
|
||||
|
||||
@@ -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"]
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -88,6 +88,10 @@ label {
|
||||
float: right;
|
||||
margin: 0;
|
||||
}
|
||||
.desc {
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
}
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user