python-kdcproxy-1.1.0-1

- New upstream version (1.1.0)
- Use DNS discovery for declared realms only (CVE-2025-59088)
  Resolves: RHEL-113677
- Fix DoS vulnerability based on unbounded TCP buffering (CVE-2025-59089)
  Resolves: RHEL-113681

Signed-off-by: Julien Rische <jrische@redhat.com>
This commit is contained in:
Julien Rische 2025-11-19 16:27:27 +01:00
parent c04b05c33a
commit e6e0f3539b
6 changed files with 32 additions and 353 deletions

2
.gitignore vendored
View File

@ -8,3 +8,5 @@
/kdcproxy-0.4.1.tar.gz
/kdcproxy-0.4.2.tar.gz
/kdcproxy-1.0.0.tar.gz
/kdcproxy-1.1.0.tar.gz
/kdcproxy-1.1.0.tar.gz.sha512sum.txt

View File

@ -1,100 +0,0 @@
From 7b7aee01d72be5a310678cdad189cb7382f28549 Mon Sep 17 00:00:00 2001
From: Robbie Harwood <rharwood@redhat.com>
Date: Tue, 19 Jan 2021 11:41:40 -0500
Subject: [PATCH] Drop coverage from tests
To my knowledge, we've never looked at or done anything with this
output. Test coverage is a noble goal, but this project is mostly
complete, so we don't expect heavy development soon.
Requested-by: Petr Viktorin <pviktori@redhat.com>
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
(cherry picked from commit 86c3da13d5d6cdb5822d194f2b820da1fd31dddb)
[rharwood@redhat.com: .gitignore]
---
.coveragerc | 23 -----------------------
MANIFEST.in | 1 -
setup.py | 2 +-
tox.ini | 12 ++----------
4 files changed, 3 insertions(+), 35 deletions(-)
delete mode 100644 .coveragerc
diff --git a/.coveragerc b/.coveragerc
deleted file mode 100644
index 4038562..0000000
--- a/.coveragerc
+++ /dev/null
@@ -1,23 +0,0 @@
-[run]
-branch = True
-source =
- kdcproxy
- tests.py
-
-[paths]
-source =
- kdcproxy
- .tox/*/lib/python*/site-packages/kdcproxy
-
-[report]
-ignore_errors = False
-precision = 1
-exclude_lines =
- pragma: no cover
- raise AssertionError
- raise NotImplementedError
- if 0:
- if False:
- if __name__ == .__main__.:
- if PY3
- if not PY3
diff --git a/MANIFEST.in b/MANIFEST.in
index 362f840..ff6b9a7 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -2,4 +2,3 @@ include README COPYING
include tox.ini
include setup.cfg
include tests.py tests.krb5.conf
-include .coveragerc
diff --git a/setup.py b/setup.py
index 20b335e..4b34fcc 100644
--- a/setup.py
+++ b/setup.py
@@ -29,7 +29,7 @@ install_requires = [
]
extras_require = {
- "tests": ["pytest", "coverage", "WebTest"],
+ "tests": ["pytest", "WebTest"],
"test_pep8": ['flake8', 'flake8-import-order', 'pep8-naming']
}
diff --git a/tox.ini b/tox.ini
index 038d996..9672cee 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,21 +1,13 @@
[tox]
minversion = 2.3.1
-envlist = py36,py37,py38,py39,pep8,py3pep8,doc,coverage-report
+envlist = py36,py37,py38,py39,pep8,py3pep8,doc
skip_missing_interpreters = true
[testenv]
deps =
.[tests]
commands =
- {envpython} -m coverage run --parallel \
- -m pytest --capture=no --strict {posargs}
-
-[testenv:coverage-report]
-deps = coverage
-skip_install = true
-commands =
- {envpython} -m coverage combine
- {envpython} -m coverage report --show-missing
+ {envpython} -m pytest --capture=no --strict {posargs}
[testenv:pep8]
basepython = python3

View File

@ -1,71 +0,0 @@
From 99babf4ba3ce4d1f5bb893e7678df44d16b74d03 Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Mon, 18 Nov 2024 10:01:16 +0100
Subject: [PATCH] Use dedicated "kdcproxy" logger
Signed-off-by: Julien Rische <jrische@redhat.com>
(cherry picked from commit c8a69dbc0777579ba3bf3d156baed0966327ebc2)
---
kdcproxy/__init__.py | 7 +++++--
kdcproxy/config/__init__.py | 7 +++++--
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/kdcproxy/__init__.py b/kdcproxy/__init__.py
index d0ca43e..ce96a0c 100644
--- a/kdcproxy/__init__.py
+++ b/kdcproxy/__init__.py
@@ -38,6 +38,9 @@ else:
import httplib
import urlparse
+logging.basicConfig()
+logger = logging.getLogger('kdcproxy')
+
class HTTPException(Exception):
@@ -327,8 +330,8 @@ class Application:
fail_socktype = self.addr2socktypename(fail_addr)
fail_ip = fail_addr[4][0]
fail_port = fail_addr[4][1]
- logging.warning("Exchange with %s:[%s]:%d failed: %s",
- fail_socktype, fail_ip, fail_port, e)
+ logger.warning("Exchange with %s:[%s]:%d failed: %s",
+ fail_socktype, fail_ip, fail_port, e)
if reply is not None:
break
diff --git a/kdcproxy/config/__init__.py b/kdcproxy/config/__init__.py
index a1435b7..8e17c5b 100644
--- a/kdcproxy/config/__init__.py
+++ b/kdcproxy/config/__init__.py
@@ -32,6 +32,9 @@ except ImportError: # Python 2.x
import dns.rdatatype
import dns.resolver
+logging.basicConfig()
+logger = logging.getLogger('kdcproxy')
+
class IResolver(object):
@@ -60,14 +63,14 @@ class KDCProxyConfig(IConfig):
try:
self.__cp.read(filenames)
except configparser.Error:
- logging.error("Unable to read config file(s): %s", filenames)
+ logger.error("Unable to read config file(s): %s", filenames)
try:
mod = self.__cp.get(self.GLOBAL, "configs")
try:
importlib.import_module("kdcproxy.config." + mod)
except ImportError as e:
- logging.log(logging.ERROR, "Error reading config: %s" % e)
+ logger.log(logging.ERROR, "Error reading config: %s" % e)
except configparser.Error:
pass
--
2.46.0

View File

@ -1,158 +0,0 @@
From 0b2efa7b2901ada01758a0525a21af5447aa647a Mon Sep 17 00:00:00 2001
From: Julien Rische <jrische@redhat.com>
Date: Mon, 18 Nov 2024 09:38:13 +0100
Subject: [PATCH] Use exponential backoff for connection retries
Calls to socket.connect() are non-blocking, hence all subsequent calls
to socket.sendall() will fail if the target KDC service is temporarily
or indefinitely unreachable. Since the kdcproxy task uses busy-looping,
it results in the journal to be flooded with warning logs.
This commit introduces a per-socket reactivation delay which increases
exponentially as the number of reties is incremented, until timeout is
reached (i.e. 100ms, 200ms, 400ms, 800ms, 1.6s, 3.2s, ...).
Signed-off-by: Julien Rische <jrische@redhat.com>
(cherry picked from commit bac3c99c1b23487e38d965a79173ce9519e19c75)
---
kdcproxy/__init__.py | 63 +++++++++++++++++++++++++++++++++++++++++---
1 file changed, 60 insertions(+), 3 deletions(-)
diff --git a/kdcproxy/__init__.py b/kdcproxy/__init__.py
index 1493b30..d0ca43e 100644
--- a/kdcproxy/__init__.py
+++ b/kdcproxy/__init__.py
@@ -61,6 +61,13 @@ class HTTPException(Exception):
return "%d %s" % (self.code, httplib.responses[self.code])
+class SocketException(Exception):
+
+ def __init__(self, message, sock):
+ super(Exception, self).__init__(message)
+ self.sockfno = sock.fileno()
+
+
class Application:
MAX_LENGTH = 128 * 1024
SOCKTYPES = {
@@ -68,10 +75,23 @@ class Application:
"udp": socket.SOCK_DGRAM,
}
+ def addr2socktypename(self, addr):
+ ret = None
+ for name in self.SOCKTYPES:
+ if self.SOCKTYPES[name] == addr[1]:
+ ret = name
+ break
+ return ret
+
def __init__(self):
self.__resolver = MetaResolver()
def __await_reply(self, pr, rsocks, wsocks, timeout):
+ starting_time = time.time()
+ send_error = None
+ recv_error = None
+ failing_sock = None
+ reactivations = {}
extra = 0
read_buffers = {}
while (timeout + extra) > time.time():
@@ -92,6 +112,12 @@ class Application:
pass
for sock in w:
+ # Fetch reactivation tuple:
+ # 1st element: reactivation index (-1 = first activation)
+ # 2nd element: planned reactivation time (0.0 = now)
+ (rn, rt) = reactivations.get(sock, (-1, 0.0))
+ if rt > time.time():
+ continue
try:
if self.sock_type(sock) == socket.SOCK_DGRAM:
# If we proxy over UDP, remove the 4-byte length
@@ -101,8 +127,13 @@ class Application:
sock.sendall(pr.request)
extra = 10 # New connections get 10 extra seconds
except Exception as e:
- logging.warning("Conection broken while writing (%s)", e)
+ send_error = e
+ failing_sock = sock
+ reactivations[sock] = (rn + 1,
+ time.time() + 2.0**(rn + 1) / 10)
continue
+ if sock in reactivations:
+ del reactivations[sock]
rsocks.append(sock)
wsocks.remove(sock)
@@ -110,7 +141,8 @@ class Application:
try:
reply = self.__handle_recv(sock, read_buffers)
except Exception as e:
- logging.warning("Connection broken while reading (%s)", e)
+ recv_error = e
+ failing_sock = sock
if self.sock_type(sock) == socket.SOCK_STREAM:
# Remove broken TCP socket from readers
rsocks.remove(sock)
@@ -118,6 +150,21 @@ class Application:
if reply is not None:
return reply
+ if reactivations:
+ raise SocketException("Timeout while sending packets after %.2fs "
+ "and %d tries: %s" % (
+ (timeout + extra) - starting_time,
+ sum(map(lambda r: r[0],
+ reactivations.values())),
+ send_error),
+ failing_sock)
+ elif recv_error is not None:
+ raise SocketException("Timeout while receiving packets after "
+ "%.2fs: %s" % (
+ (timeout + extra) - starting_time,
+ recv_error),
+ failing_sock)
+
return None
def __handle_recv(self, sock, read_buffers):
@@ -215,6 +262,7 @@ class Application:
reply = None
wsocks = []
rsocks = []
+ sockfno2addr = {}
for server in map(urlparse.urlparse, servers):
# Enforce valid, supported URIs
scheme = server.scheme.lower().split("+", 1)
@@ -261,6 +309,7 @@ class Application:
continue
except io.BlockingIOError:
pass
+ sockfno2addr[sock.fileno()] = addr
wsocks.append(sock)
# Resend packets to UDP servers
@@ -271,7 +320,15 @@ class Application:
# Call select()
timeout = time.time() + (15 if addr is None else 2)
- reply = self.__await_reply(pr, rsocks, wsocks, timeout)
+ try:
+ reply = self.__await_reply(pr, rsocks, wsocks, timeout)
+ except SocketException as e:
+ fail_addr = sockfno2addr[e.sockfno]
+ fail_socktype = self.addr2socktypename(fail_addr)
+ fail_ip = fail_addr[4][0]
+ fail_port = fail_addr[4][1]
+ logging.warning("Exchange with %s:[%s]:%d failed: %s",
+ fail_socktype, fail_ip, fail_port, e)
if reply is not None:
break
--
2.46.0

View File

@ -1,31 +1,32 @@
%global realname kdcproxy
Name: python-%{realname}
Version: 1.0.0
Release: 8%{?dist}
Version: 1.1.0
Release: 1%{?dist}
Summary: MS-KKDCP (kerberos proxy) WSGI module
License: MIT
URL: https://github.com/latchset/%{realname}
Source0: https://github.com/latchset/%{realname}/archive/%{realname}-%{version}.tar.gz
Source0: https://github.com/latchset/%{realname}/releases/download/v%{version}/%{realname}-%{version}.tar.gz
Source1: https://github.com/latchset/%{realname}/releases/download/v%{version}/%{realname}-%{version}.tar.gz.sha512sum.txt
Patch0: Drop-coverage-from-tests.patch
Patch1: Use-exponential-backoff-for-connection-retries.patch
Patch2: Use-dedicated-kdcproxy-logger.patch
# Patches
BuildArch: noarch
BuildRequires: git
BuildRequires: python3-devel
BuildRequires: python3-dns
BuildRequires: python3-pyasn1
BuildRequires: git-core
BuildRequires: python3-pytest
BuildRequires: python3-setuptools
%description
%generate_buildrequires
%pyproject_buildrequires
%global _description %{expand:
This package contains a Python WSGI module for proxying KDC requests over
HTTP by following the MS-KKDCP protocol. It aims to be simple to deploy, with
minimal configuration.
}
%description %{_description}
%package -n python3-%{realname}
Summary: MS-KKDCP (kerberos proxy) WSGI module
@ -34,30 +35,34 @@ Requires: python3-pyasn1
%{?python_provide:%python_provide python3-%{realname}}
%description -n python3-%{realname}
This package contains a Python 3.x WSGI module for proxying KDC requests over
HTTP by following the MS-KKDCP protocol. It aims to be simple to deploy, with
minimal configuration.
%description -n python3-%{realname} %{_description}
%prep
%autosetup -S git -n %{realname}-%{version}
%autosetup -S git_am -n %{realname}-%{version}
%build
%py3_build
%pyproject_wheel
%install
%py3_install
%pyproject_install
%pyproject_save_files %{realname}
%check
%{__python3} -m pytest
%pyproject_check_import
%pytest
%files -n python3-%{realname}
%files -n python%{python3_pkgversion}-%{realname} -f %{pyproject_files}
%doc README
%license COPYING
%{python3_sitelib}/%{realname}/
%{python3_sitelib}/%{realname}-%{version}-*.egg-info
%changelog
* Wed Nov 19 2025 Julien Rische <jrische@redhat.com> - 1.1.0-1
- New upstream version (1.1.0)
- Use DNS discovery for declared realms only (CVE-2025-59088)
Resolves: RHEL-113677
- Fix DoS vulnerability based on unbounded TCP buffering (CVE-2025-59089)
Resolves: RHEL-113681
* Fri Nov 22 2024 Julien Rische <jrische@redhat.com> - 1.0.0-8
- Log KDC timeout only once per request
Resolves: RHEL-68355

View File

@ -1 +1,2 @@
SHA512 (kdcproxy-1.0.0.tar.gz) = 617dba929d1c87c60d9a321269fd23348af11eabd8db3cea4b4750ec9514c9dce3487e658c396a5d009c9ef92326d45f5f00a2a116ab6469c62eda8270e55391
SHA512 (kdcproxy-1.1.0.tar.gz) = f03b9d40d71322281d0197df6fe6b5936a8d09b0fee49fc5375b61974d005cedc5645f92a223d221c05c6ffd2613a86eb7d7295c4ac27a2f2c9eaa10fa24c182
SHA512 (kdcproxy-1.1.0.tar.gz.sha512sum.txt) = b08dae1d80ef1c3dd2ff9a5da6411255860c229bc5da46d8ed85b3998f1d417c0b783912320d7e0d780956c117ad4c77699e5d68a61c44853014a5f985301fbd