Import from CS git
This commit is contained in:
parent
892a31ab5a
commit
319fdcb0c6
@ -0,0 +1,265 @@
|
|||||||
|
From 69b0fd6d77ea5968bd815188ee2bda3d282ebc60 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Jan Grulich <jgrulich@redhat.com>
|
||||||
|
Date: Mon, 29 Jul 2024 14:31:14 +0200
|
||||||
|
Subject: [PATCH] Add option allowing to connect only the user owning the
|
||||||
|
running session
|
||||||
|
|
||||||
|
Checks, whether the user who is trying to authenticate is already logged
|
||||||
|
into the running session in order to allow or reject the connection.
|
||||||
|
This is expected to be used with 'plain' security type in combination
|
||||||
|
with 'PlainUsers=*' option allowing everyone to connect to the session.
|
||||||
|
---
|
||||||
|
common/rfb/VNCServerST.cxx | 7 --
|
||||||
|
unix/x0vncserver/XDesktop.cxx | 8 ++
|
||||||
|
unix/xserver/hw/vnc/XserverDesktop.cc | 137 ++++++++++++++++++++++++++
|
||||||
|
unix/xserver/hw/vnc/XserverDesktop.h | 7 ++
|
||||||
|
unix/xserver/hw/vnc/Xvnc.man | 7 ++
|
||||||
|
5 files changed, 159 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx
|
||||||
|
index b99d33b..aa8d53e 100644
|
||||||
|
--- a/common/rfb/VNCServerST.cxx
|
||||||
|
+++ b/common/rfb/VNCServerST.cxx
|
||||||
|
@@ -682,13 +682,6 @@ void VNCServerST::queryConnection(VNCSConnectionST* client,
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- // - Are we configured to do queries?
|
||||||
|
- if (!rfb::Server::queryConnect &&
|
||||||
|
- !client->getSock()->requiresQuery()) {
|
||||||
|
- approveConnection(client->getSock(), true, nullptr);
|
||||||
|
- return;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
// - Does the client have the right to bypass the query?
|
||||||
|
if (client->accessCheck(AccessNoQuery))
|
||||||
|
{
|
||||||
|
diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx
|
||||||
|
index b43e3f7..3d00e23 100644
|
||||||
|
--- a/unix/x0vncserver/XDesktop.cxx
|
||||||
|
+++ b/unix/x0vncserver/XDesktop.cxx
|
||||||
|
@@ -31,6 +31,7 @@
|
||||||
|
#include <network/Socket.h>
|
||||||
|
|
||||||
|
#include <rfb/LogWriter.h>
|
||||||
|
+#include <rfb/ServerCore.h>
|
||||||
|
|
||||||
|
#include <x0vncserver/XDesktop.h>
|
||||||
|
|
||||||
|
@@ -320,6 +321,13 @@ void XDesktop::queryConnection(network::Socket* sock,
|
||||||
|
{
|
||||||
|
assert(isRunning());
|
||||||
|
|
||||||
|
+ // - Are we configured to do queries?
|
||||||
|
+ if (!rfb::Server::queryConnect &&
|
||||||
|
+ !sock->requiresQuery()) {
|
||||||
|
+ server->approveConnection(sock, true, nullptr);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// Someone already querying?
|
||||||
|
if (queryConnectSock) {
|
||||||
|
std::list<network::Socket*> sockets;
|
||||||
|
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc
|
||||||
|
index 260ed3a..c8741f6 100644
|
||||||
|
--- a/unix/xserver/hw/vnc/XserverDesktop.cc
|
||||||
|
+++ b/unix/xserver/hw/vnc/XserverDesktop.cc
|
||||||
|
@@ -51,6 +51,11 @@
|
||||||
|
#include "XorgGlue.h"
|
||||||
|
#include "vncInput.h"
|
||||||
|
|
||||||
|
+#if HAVE_SYSTEMD_DAEMON
|
||||||
|
+# include <pwd.h>
|
||||||
|
+# include <systemd/sd-login.h>
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
extern "C" {
|
||||||
|
void vncSetGlueContext(int screenIndex);
|
||||||
|
void vncPresentMscEvent(uint64_t id, uint64_t msc);
|
||||||
|
@@ -71,6 +76,15 @@ IntParameter queryConnectTimeout("QueryConnectTimeout",
|
||||||
|
"rejecting the connection",
|
||||||
|
10);
|
||||||
|
|
||||||
|
+#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
|
+BoolParameter approveLoggedUserOnly
|
||||||
|
+("ApproveLoggedUserOnly",
|
||||||
|
+ "Approve only the user who is currently logged into the session."
|
||||||
|
+ "This is expected to be combined with 'plain' security type and with "
|
||||||
|
+ "'PlainUsers=*' option allowing everyone to connect to the session."
|
||||||
|
+ "Default is off.",
|
||||||
|
+ false);
|
||||||
|
+#endif
|
||||||
|
|
||||||
|
XserverDesktop::XserverDesktop(int screenIndex_,
|
||||||
|
std::list<network::SocketListener*> listeners_,
|
||||||
|
@@ -164,11 +178,134 @@ void XserverDesktop::init(rfb::VNCServer* vs)
|
||||||
|
// ready state
|
||||||
|
}
|
||||||
|
|
||||||
|
+#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
|
+bool XserverDesktop::checkUserLogged(const char* userName)
|
||||||
|
+{
|
||||||
|
+ bool ret = false;
|
||||||
|
+ bool noUserSession = true;
|
||||||
|
+ int res;
|
||||||
|
+ char **sessions;
|
||||||
|
+
|
||||||
|
+ res = sd_get_sessions(&sessions);
|
||||||
|
+ if (res < 0) {
|
||||||
|
+ vlog.debug("logind: failed to get sessions");
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (sessions != nullptr && sessions[0] != nullptr) {
|
||||||
|
+ for (int i = 0; sessions[i]; i++) {
|
||||||
|
+ uid_t uid;
|
||||||
|
+ char *clazz;
|
||||||
|
+ char *display;
|
||||||
|
+ char *type;
|
||||||
|
+ char *state;
|
||||||
|
+
|
||||||
|
+ res = sd_session_get_type(sessions[i], &type);
|
||||||
|
+ if (res < 0) {
|
||||||
|
+ vlog.debug("logind: failed to determine session type");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (strcmp(type, "x11") != 0) {
|
||||||
|
+ free(type);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ free(type);
|
||||||
|
+
|
||||||
|
+ res = sd_session_get_display(sessions[i], &display);
|
||||||
|
+ if (res < 0) {
|
||||||
|
+ vlog.debug("logind: failed to determine display of session");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ std::string serverDisplay = ":" + std::to_string(screenIndex);
|
||||||
|
+ std::string serverDisplayIPv4 = "127.0.0.1:" + std::to_string(screenIndex);
|
||||||
|
+ std::string serverDisplayIPv6 = "::1:" + std::to_string(screenIndex);
|
||||||
|
+ if ((strcmp(display, serverDisplay.c_str()) != 0) &&
|
||||||
|
+ (strcmp(display, serverDisplayIPv4.c_str()) != 0) &&
|
||||||
|
+ (strcmp(display, serverDisplayIPv6.c_str()) != 0)) {
|
||||||
|
+ free(display);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ free(display);
|
||||||
|
+
|
||||||
|
+ res = sd_session_get_class(sessions[i], &clazz);
|
||||||
|
+ if (res < 0) {
|
||||||
|
+ vlog.debug("logind: failed to determine session class");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ res = sd_session_get_state(sessions[i], &state);
|
||||||
|
+ if (res < 0) {
|
||||||
|
+ vlog.debug("logind: failed to determine session state");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (strcmp(state, "closing") == 0) {
|
||||||
|
+ free(state);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ free(state);
|
||||||
|
+
|
||||||
|
+ res = sd_session_get_uid(sessions[i], &uid);
|
||||||
|
+ if (res < 0) {
|
||||||
|
+ vlog.debug("logind: failed to determine user id of session");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (uid != 0 && strcmp(clazz, "user") == 0) {
|
||||||
|
+ noUserSession = false;
|
||||||
|
+ }
|
||||||
|
+ free(clazz);
|
||||||
|
+
|
||||||
|
+ struct passwd *pw = getpwnam(userName);
|
||||||
|
+ if (!pw) {
|
||||||
|
+ vlog.debug("logind: user not found");
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (uid == pw->pw_uid) {
|
||||||
|
+ ret = true;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (sessions) {
|
||||||
|
+ for (int i = 0; sessions[i]; i ++) {
|
||||||
|
+ free(sessions[i]);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ free (sessions);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // If we didn't find a matching user, we can still allow the user
|
||||||
|
+ // to log in if there is no user session yet.
|
||||||
|
+ return !ret ? noUserSession : ret;
|
||||||
|
+}
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
void XserverDesktop::queryConnection(network::Socket* sock,
|
||||||
|
const char* userName)
|
||||||
|
{
|
||||||
|
int count;
|
||||||
|
|
||||||
|
+#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
|
+ // - Only owner of the session can be approved
|
||||||
|
+ if (approveLoggedUserOnly && !checkUserLogged(userName)) {
|
||||||
|
+ server->approveConnection(sock, false,
|
||||||
|
+ "The user is not owner of the running session");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
+ // - Are we configured to do queries?
|
||||||
|
+ if (!rfb::Server::queryConnect &&
|
||||||
|
+ !sock->requiresQuery()) {
|
||||||
|
+ server->approveConnection(sock, true, nullptr);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (queryConnectTimer.isStarted()) {
|
||||||
|
server->approveConnection(sock, false, "Another connection is currently being queried.");
|
||||||
|
return;
|
||||||
|
diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h
|
||||||
|
index 8c543db..8d6bde4 100644
|
||||||
|
--- a/unix/xserver/hw/vnc/XserverDesktop.h
|
||||||
|
+++ b/unix/xserver/hw/vnc/XserverDesktop.h
|
||||||
|
@@ -108,6 +108,13 @@ public:
|
||||||
|
void grabRegion(const rfb::Region& r) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
+#ifdef HAVE_SYSTEMD_DAEMON
|
||||||
|
+ // - Check whether user is logged into a session
|
||||||
|
+ // Returns true if user is already logged or there is no
|
||||||
|
+ // user session at all.
|
||||||
|
+ bool checkUserLogged(const char* userName);
|
||||||
|
+#endif
|
||||||
|
+
|
||||||
|
bool handleListenerEvent(int fd,
|
||||||
|
std::list<network::SocketListener*>* sockets,
|
||||||
|
rfb::VNCServer* sockserv);
|
||||||
|
diff --git a/unix/xserver/hw/vnc/Xvnc.man b/unix/xserver/hw/vnc/Xvnc.man
|
||||||
|
index d6b1664..24384df 100644
|
||||||
|
--- a/unix/xserver/hw/vnc/Xvnc.man
|
||||||
|
+++ b/unix/xserver/hw/vnc/Xvnc.man
|
||||||
|
@@ -200,6 +200,13 @@ Never treat incoming connections as shared, regardless of the client-specified
|
||||||
|
setting. Default is off.
|
||||||
|
.
|
||||||
|
.TP
|
||||||
|
+.B \-ApproveLoggedUserOnly
|
||||||
|
+Approve only the user who is currently logged into the session.
|
||||||
|
+This is expected to be combined with "Plain" security type and with
|
||||||
|
+"PlainUsers=*" option allowing everyone to connect to the session.
|
||||||
|
+Default is off.
|
||||||
|
+.
|
||||||
|
+.TP
|
||||||
|
.B \-pam_service \fIname\fP, \-PAMService \fIname\fP
|
||||||
|
PAM service name to use when authentication users using any of the "Plain"
|
||||||
|
security types. Default is \fBvnc\fP.
|
@ -0,0 +1,14 @@
|
|||||||
|
diff --git a/unix/vncpasswd/vncpasswd.cxx b/unix/vncpasswd/vncpasswd.cxx
|
||||||
|
index 466aa1a2..197d60dc 100644
|
||||||
|
--- a/unix/vncpasswd/vncpasswd.cxx
|
||||||
|
+++ b/unix/vncpasswd/vncpasswd.cxx
|
||||||
|
@@ -147,8 +147,7 @@ static std::vector<uint8_t> readpassword() {
|
||||||
|
}
|
||||||
|
|
||||||
|
if (first.size() > 8) {
|
||||||
|
- fprintf(stderr,"Password should not be greater than 8 characters\nBecause only 8 valid characters are used - try again\n");
|
||||||
|
- continue;
|
||||||
|
+ fprintf(stderr,"Password should not be greater than 8 characters\nBecause only 8 valid characters are used\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef HAVE_PWQUALITY
|
@ -0,0 +1,47 @@
|
|||||||
|
From 1f1aaca09a1f9919f5169caea9c396b14c2af765 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Pierre Ossman <ossman@cendio.se>
|
||||||
|
Date: Tue, 8 Apr 2025 14:41:04 +0200
|
||||||
|
Subject: [PATCH] Don't print Xvnc banner before parsing args
|
||||||
|
|
||||||
|
If we'll be running in inetd mode, then stdout and stderr will be a
|
||||||
|
client socket and not an appropriate place for logging.
|
||||||
|
|
||||||
|
Mimic what Xorg does instead.
|
||||||
|
---
|
||||||
|
unix/xserver/hw/vnc/xvnc.c | 9 +++++----
|
||||||
|
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/unix/xserver/hw/vnc/xvnc.c b/unix/xserver/hw/vnc/xvnc.c
|
||||||
|
index ddb249937..a13168c47 100644
|
||||||
|
--- a/unix/xserver/hw/vnc/xvnc.c
|
||||||
|
+++ b/unix/xserver/hw/vnc/xvnc.c
|
||||||
|
@@ -446,7 +446,7 @@ ddxProcessArgument(int argc, char *argv[], int i)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!strcmp(argv[i], "-showconfig") || !strcmp(argv[i], "-version")) {
|
||||||
|
- /* Already shown at start */
|
||||||
|
+ vncPrintBanner();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1171,8 +1171,11 @@ InitOutput(ScreenInfo * scrInfo, int argc, char **argv)
|
||||||
|
int i;
|
||||||
|
int NumFormats = 0;
|
||||||
|
|
||||||
|
- if (serverGeneration == 1)
|
||||||
|
+ if (serverGeneration == 1) {
|
||||||
|
+ vncPrintBanner();
|
||||||
|
+
|
||||||
|
LoadExtensionList(vncExtensions, ARRAY_SIZE(vncExtensions), TRUE);
|
||||||
|
+ }
|
||||||
|
|
||||||
|
#if XORG_AT_LEAST(1, 20, 0)
|
||||||
|
xorgGlxCreateVendor();
|
||||||
|
@@ -1266,7 +1269,5 @@ vncClientGone(int fd)
|
||||||
|
int
|
||||||
|
main(int argc, char *argv[], char *envp[])
|
||||||
|
{
|
||||||
|
- vncPrintBanner();
|
||||||
|
-
|
||||||
|
return dix_main(argc, argv, envp);
|
||||||
|
}
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
Name: tigervnc
|
Name: tigervnc
|
||||||
Version: 1.15.0
|
Version: 1.15.0
|
||||||
Release: 1%{?dist}
|
Release: 5%{?dist}
|
||||||
Summary: A TigerVNC remote display system
|
Summary: A TigerVNC remote display system
|
||||||
|
|
||||||
%global _hardened_build 1
|
%global _hardened_build 1
|
||||||
@ -26,10 +26,15 @@ Patch1: tigervnc-use-gnome-as-default-session.patch
|
|||||||
# https://github.com/TigerVNC/tigervnc/pull/1425
|
# https://github.com/TigerVNC/tigervnc/pull/1425
|
||||||
Patch2: tigervnc-vncsession-restore-script-systemd-service.patch
|
Patch2: tigervnc-vncsession-restore-script-systemd-service.patch
|
||||||
Patch3: tigervnc-dont-install-appstream-metadata-file.patch
|
Patch3: tigervnc-dont-install-appstream-metadata-file.patch
|
||||||
|
# Only warn about passwords longer than 8 characters, but allow them to be used as in the past
|
||||||
|
Patch4: tigervnc-allow-use-of-passwords-longer-than-eight-characters.patch
|
||||||
|
# https://github.com/TigerVNC/tigervnc/pull/1792
|
||||||
|
Patch5: tigervnc-add-option-allowing-to-connect-only-user-owning-session.patch
|
||||||
|
|
||||||
# Upstream patches
|
# Upstream patches
|
||||||
Patch50: tigervnc-add-selinux-policy-rules-allowing-create-dirs-under-root-dir.patch
|
Patch50: tigervnc-add-selinux-policy-rules-allowing-create-dirs-under-root-dir.patch
|
||||||
Patch51: tigervnc-add-selinux-policy-rules-allowing-access-to-proc-sys-fs-nr-open.patch
|
Patch51: tigervnc-add-selinux-policy-rules-allowing-access-to-proc-sys-fs-nr-open.patch
|
||||||
|
Patch52: tigervnc-dont-print-xvnc-banner-before-parsing-args.patch
|
||||||
|
|
||||||
# Upstreamable patches
|
# Upstreamable patches
|
||||||
|
|
||||||
@ -102,6 +107,11 @@ BuildRequires: xorg-x11-xtrans-devel
|
|||||||
BuildRequires: libselinux-devel
|
BuildRequires: libselinux-devel
|
||||||
BuildRequires: selinux-policy-devel
|
BuildRequires: selinux-policy-devel
|
||||||
|
|
||||||
|
# For RHEL-91104
|
||||||
|
BuildRequires: pkgconfig(dbus-1) >= 1.0
|
||||||
|
BuildRequires: pkgconfig(libsystemd) >= 209
|
||||||
|
BuildRequires: pkgconfig(libudev) >= 143
|
||||||
|
|
||||||
Requires(post): coreutils
|
Requires(post): coreutils
|
||||||
Requires(postun):coreutils
|
Requires(postun):coreutils
|
||||||
|
|
||||||
@ -225,10 +235,13 @@ popd
|
|||||||
%patch -P1 -p1 -b .use-gnome-as-default-session
|
%patch -P1 -p1 -b .use-gnome-as-default-session
|
||||||
%patch -P2 -p1 -b .vncsession-restore-script-systemd-service
|
%patch -P2 -p1 -b .vncsession-restore-script-systemd-service
|
||||||
%patch -P3 -p1 -b .dont-install-appstream-metadata-file.patch
|
%patch -P3 -p1 -b .dont-install-appstream-metadata-file.patch
|
||||||
|
%patch -P4 -p1 -b .allow-use-of-passwords-longer-than-eight-characters
|
||||||
|
%patch -P5 -p1 -b .add-option-allowing-to-connect-only-user-owning-session
|
||||||
|
|
||||||
# Upstream patches
|
# Upstream patches
|
||||||
%patch -P50 -p1 -b .add-selinux-policy-rules-allowing-create-dirs-under-root-dir
|
%patch -P50 -p1 -b .add-selinux-policy-rules-allowing-create-dirs-under-root-dir
|
||||||
%patch -P51 -p1 -b .add-selinux-policy-rules-allowing-access-to-proc-sys-fs-nr-open
|
%patch -P51 -p1 -b .add-selinux-policy-rules-allowing-access-to-proc-sys-fs-nr-open
|
||||||
|
%patch -P52 -p1 -b .dont-print-xvnc-banner-before-parsing-args
|
||||||
|
|
||||||
# Upstreamable patches
|
# Upstreamable patches
|
||||||
|
|
||||||
@ -257,7 +270,9 @@ autoreconf -fiv
|
|||||||
--disable-config-udev \
|
--disable-config-udev \
|
||||||
--without-dtrace \
|
--without-dtrace \
|
||||||
--disable-devel-docs \
|
--disable-devel-docs \
|
||||||
--disable-selective-werror
|
--disable-selective-werror \
|
||||||
|
--enable-systemd-logind \
|
||||||
|
--enable-config-udev
|
||||||
|
|
||||||
make %{?_smp_mflags}
|
make %{?_smp_mflags}
|
||||||
popd
|
popd
|
||||||
@ -382,6 +397,23 @@ fi
|
|||||||
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}
|
%ghost %verify(not md5 size mode mtime) %{_sharedstatedir}/selinux/%{selinuxtype}/active/modules/200/%{modulename}
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue May 27 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-5
|
||||||
|
- Fix broken authentication with x0vncserver
|
||||||
|
Resolves: RHEL-93729
|
||||||
|
|
||||||
|
* Thu May 15 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-4
|
||||||
|
- Add option "ApproveLoggedUserOnly" allowing to connect only the user
|
||||||
|
owning the running session
|
||||||
|
Resolves: RHEL-91104
|
||||||
|
|
||||||
|
* Wed Apr 30 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-3
|
||||||
|
- Only warn about 8 characters limit, but let it proceed
|
||||||
|
Resolves: RHEL-89430
|
||||||
|
|
||||||
|
* Wed Apr 16 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-2
|
||||||
|
- Fix inetd mode not working
|
||||||
|
Resolves: RHEL-86513
|
||||||
|
|
||||||
* Wed Feb 26 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-1
|
* Wed Feb 26 2025 Jan Grulich <jgrulich@redhat.com> - 1.15.0-1
|
||||||
- 1.15.0
|
- 1.15.0
|
||||||
Resolves: RHEL-79161
|
Resolves: RHEL-79161
|
||||||
|
Loading…
Reference in New Issue
Block a user