Add opt-in Plasma fingerprint workaround
This commit is contained in:
@@ -17,6 +17,7 @@ sudo dnf config-manager addrepo \
|
|||||||
sudo dnf install touchpad-hold-tap
|
sudo dnf install touchpad-hold-tap
|
||||||
sudo dnf install plasma-always-show-unlock
|
sudo dnf install plasma-always-show-unlock
|
||||||
sudo dnf install plasma-task-group-shortcuts
|
sudo dnf install plasma-task-group-shortcuts
|
||||||
|
sudo dnf install plasma-fingerprint-workaround
|
||||||
```
|
```
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
@@ -82,3 +83,20 @@ removing it, restore them with:
|
|||||||
```bash
|
```bash
|
||||||
plasma-task-group-shortcuts --restore-shortcuts
|
plasma-task-group-shortcuts --restore-shortcuts
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Plasma fingerprint workaround
|
||||||
|
|
||||||
|
Experimental and unaudited. The `plasma-fingerprint-workaround` package is an
|
||||||
|
inert controller for installing a patched Fedora KScreenLocker build that
|
||||||
|
recovers fingerprint authentication after suspend. It makes no lock-screen
|
||||||
|
changes when installed and must be enabled explicitly:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo plasma-fingerprint-workaround enable
|
||||||
|
```
|
||||||
|
|
||||||
|
The patched build is not present in the DNF repository and therefore cannot be
|
||||||
|
selected by a normal system update. The controller can also install a locally
|
||||||
|
built RPM and restore Fedora's original package. See the tool's
|
||||||
|
[`README`](plasma-fingerprint-workaround/README.md) for the security warning,
|
||||||
|
build instructions, version checks, and force-downgrade option.
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# Plasma fingerprint workaround
|
||||||
|
|
||||||
|
This is an experimental and unaudited replacement for Fedora's KScreenLocker
|
||||||
|
package. It changes security-sensitive session-locking and authentication code.
|
||||||
|
Review the patches and build the package yourself if you do not trust the
|
||||||
|
provided binary.
|
||||||
|
|
||||||
|
Installing `plasma-fingerprint-workaround` does not enable the workaround or
|
||||||
|
modify KScreenLocker. The controller only acts when explicitly asked:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo plasma-fingerprint-workaround enable
|
||||||
|
plasma-fingerprint-workaround status
|
||||||
|
sudo plasma-fingerprint-workaround disable
|
||||||
|
```
|
||||||
|
|
||||||
|
The default payload is kept outside the DNF repository. The controller checks
|
||||||
|
its pinned SHA-256 digest, RPM integrity, package name, architecture, and
|
||||||
|
workaround metadata before asking DNF to install it. Disabling the workaround
|
||||||
|
restores the current KScreenLocker package from Fedora's `fedora` or `updates`
|
||||||
|
repository.
|
||||||
|
|
||||||
|
The provided build currently supports Fedora 44 on x86_64 and is based on
|
||||||
|
`kscreenlocker-6.7.4-1.fc44`. A different base version is rejected by default.
|
||||||
|
To intentionally install the older provided build after a KScreenLocker update:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo plasma-fingerprint-workaround enable --force
|
||||||
|
```
|
||||||
|
|
||||||
|
## Locally built package
|
||||||
|
|
||||||
|
Build dependencies can be installed and the package built with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo dnf5 builddep plasma-fingerprint-workaround/kscreenlocker/kscreenlocker.spec
|
||||||
|
./scripts/build-patched-kscreenlocker-rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
Install the resulting package directly through the controller:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo plasma-fingerprint-workaround enable \
|
||||||
|
--rpm rpmbuild/RPMS/x86_64/kscreenlocker-6.7.4-1.fc44.ajp5.x86_64.rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
For another upstream version, supply its version, Fedora base release, and
|
||||||
|
source archive checksum. The patches must still apply and compile cleanly.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
KSCREENLOCKER_VERSION=6.7.5 \
|
||||||
|
KSCREENLOCKER_BASE_RELEASE=1 \
|
||||||
|
KSCREENLOCKER_SOURCE_SHA256=SHA256 \
|
||||||
|
./scripts/build-patched-kscreenlocker-rpm
|
||||||
|
```
|
||||||
|
|
||||||
|
A locally built package based on a different installed version requires
|
||||||
|
`--force`. This flag permits the version mismatch and allows DNF to downgrade;
|
||||||
|
it does not bypass the package identity, architecture, integrity, or workaround
|
||||||
|
metadata checks.
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
%{!?upstream_version:%global upstream_version 6.7.4}
|
||||||
|
%{!?base_release:%global base_release 1}
|
||||||
|
%{!?workaround_release:%global workaround_release 5}
|
||||||
|
|
||||||
|
Name: kscreenlocker
|
||||||
|
Version: %{upstream_version}
|
||||||
|
Release: %{base_release}%{?dist}.ajp%{workaround_release}
|
||||||
|
Summary: Library and components for secure lock screen architecture
|
||||||
|
|
||||||
|
License: BSD-3-Clause AND CC0-1.0 AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-only AND LGPL-2.1-only AND LGPL-3.0-only AND (GPL-2.0-only OR GPL-3.0-only) AND (LGPL-2.1-only OR LGPL-3.0-only)
|
||||||
|
URL: https://invent.kde.org/plasma/%{name}
|
||||||
|
Source0: https://download.kde.org/stable/plasma/%{version}/%{name}-%{version}.tar.xz
|
||||||
|
Source1: restart-fprintd-after-resume
|
||||||
|
|
||||||
|
Patch0: 0001-dont-cancel-authentication-on-suspend.patch
|
||||||
|
Patch1: 0002-allow-retrying-noninteractive-authentication.patch
|
||||||
|
Patch2: 0003-allow-retry-after-transient-auth-unavailability.patch
|
||||||
|
Patch3: 0004-retry-transient-unavailability-for-fingerprint-only.patch
|
||||||
|
|
||||||
|
# Marks packages that the controller may install and records the Fedora build
|
||||||
|
# on which the patches were based.
|
||||||
|
Provides: plasma-fingerprint-workaround-payload = 1
|
||||||
|
Provides: plasma-fingerprint-workaround-base = %{version}-%{base_release}%{?dist}
|
||||||
|
Provides: kscreenlocker = %{version}-%{base_release}%{?dist}
|
||||||
|
|
||||||
|
# Help upgrades; kscreenlocker was split from plasma-workspace in Plasma 5.5.
|
||||||
|
Conflicts: plasma-workspace < 5.5
|
||||||
|
|
||||||
|
BuildRequires: cmake(LayerShellQt)
|
||||||
|
BuildRequires: perl-generators
|
||||||
|
BuildRequires: qt6-qtbase-devel
|
||||||
|
BuildRequires: qt6-qtbase-private-devel
|
||||||
|
BuildRequires: cmake(Qt6Quick)
|
||||||
|
BuildRequires: kf6-rpm-macros
|
||||||
|
BuildRequires: extra-cmake-modules
|
||||||
|
BuildRequires: cmake(KF6Crash)
|
||||||
|
BuildRequires: cmake(KF6GlobalAccel)
|
||||||
|
BuildRequires: cmake(KF6I18n)
|
||||||
|
BuildRequires: cmake(KF6IdleTime)
|
||||||
|
BuildRequires: cmake(KF6KCMUtils)
|
||||||
|
BuildRequires: cmake(KF6KIO)
|
||||||
|
BuildRequires: cmake(KF6Notifications)
|
||||||
|
BuildRequires: cmake(KF6Screen)
|
||||||
|
BuildRequires: cmake(KF6Solid)
|
||||||
|
BuildRequires: cmake(KF6Svg)
|
||||||
|
BuildRequires: cmake(KF6XmlGui)
|
||||||
|
BuildRequires: cmake(KF6GuiAddons)
|
||||||
|
BuildRequires: cmake(KF6KirigamiPlatform)
|
||||||
|
BuildRequires: libX11-devel
|
||||||
|
BuildRequires: xcb-util-keysyms-devel
|
||||||
|
BuildRequires: wayland-devel
|
||||||
|
BuildRequires: pkgconfig(xi)
|
||||||
|
BuildRequires: pkgconfig(xcb-event)
|
||||||
|
BuildRequires: cmake(PlasmaQuick)
|
||||||
|
BuildRequires: libXcursor-devel
|
||||||
|
BuildRequires: pam-devel
|
||||||
|
|
||||||
|
%description
|
||||||
|
%{summary}.
|
||||||
|
|
||||||
|
This experimental Fedora 44 build contains local fingerprint authentication
|
||||||
|
workarounds. It has not received the security review of Fedora's package.
|
||||||
|
|
||||||
|
%package devel
|
||||||
|
Summary: Development files for %{name}
|
||||||
|
Requires: %{name}%{?_isa} = %{version}-%{release}
|
||||||
|
|
||||||
|
%description devel
|
||||||
|
The %{name}-devel package contains libraries and header files for developing
|
||||||
|
applications that use %{name}.
|
||||||
|
|
||||||
|
%prep
|
||||||
|
%autosetup -p1
|
||||||
|
|
||||||
|
%build
|
||||||
|
%cmake_kf6
|
||||||
|
%cmake_build
|
||||||
|
|
||||||
|
%install
|
||||||
|
%cmake_install
|
||||||
|
install -D -m 0755 %{SOURCE1} \
|
||||||
|
%{buildroot}%{_prefix}/lib/systemd/system-sleep/restart-fprintd-after-resume
|
||||||
|
|
||||||
|
%find_lang %{name} --with-qt --all-name
|
||||||
|
|
||||||
|
%files -f %{name}.lang
|
||||||
|
%license COPYING
|
||||||
|
%{_kf6_libdir}/libKScreenLocker.so.*
|
||||||
|
%{_kf6_datadir}/knotifications6/*.notifyrc
|
||||||
|
%{_libexecdir}/kscreenlocker_greet
|
||||||
|
%dir %{_kf6_datadir}/ksmserver/
|
||||||
|
%{_kf6_datadir}/ksmserver/screenlocker/
|
||||||
|
%{_kf6_datadir}/applications/kcm_screenlocker.desktop
|
||||||
|
%{_kf6_qtplugindir}/plasma/kcms/systemsettings/kcm_screenlocker.so
|
||||||
|
%{_kf6_datadir}/qlogging-categories6/kscreenlocker.categories
|
||||||
|
%{_prefix}/lib/systemd/system-sleep/restart-fprintd-after-resume
|
||||||
|
|
||||||
|
%files devel
|
||||||
|
%{_kf6_libdir}/libKScreenLocker.so
|
||||||
|
%{_kf6_libdir}/cmake/ScreenSaverDBusInterface/
|
||||||
|
%{_kf6_libdir}/cmake/KScreenLocker/
|
||||||
|
%{_includedir}/KScreenLocker/
|
||||||
|
%{_datadir}/dbus-1/interfaces/*.xml
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Fri Sep 04 2026 Anton - 6.7.4-1.fc44.ajp5
|
||||||
|
- Package the fprintd resume hook and compatibility metadata
|
||||||
|
- Apply the tested fingerprint retry patch set
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
From: Alex Sanchez-Stern <alex@dmodel.ai>
|
||||||
|
Subject: [PATCH] Don't cancel in-progress authentication on suspend
|
||||||
|
|
||||||
|
Aborting an in-progress PAM conversation when the system suspends makes
|
||||||
|
pam_authenticate() report a failure. The greeter then displays a failed
|
||||||
|
login on resume, and authentication backends such as fingerprint can be
|
||||||
|
left unusable for the remainder of that lock-screen session.
|
||||||
|
|
||||||
|
Leave the conversation parked across suspend and resume instead. This is
|
||||||
|
the change proposed upstream in KScreenLocker merge request 340, adapted
|
||||||
|
to the Plasma 6.7.4 source shipped by Fedora 44.
|
||||||
|
---
|
||||||
|
greeter/greeterapp.cpp | 6 ------
|
||||||
|
greeter/greeterapp.h | 2 --
|
||||||
|
2 files changed, 8 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/greeter/greeterapp.cpp b/greeter/greeterapp.cpp
|
||||||
|
index b1de459..08d8134 100644
|
||||||
|
--- a/greeter/greeterapp.cpp
|
||||||
|
+++ b/greeter/greeterapp.cpp
|
||||||
|
@@ -10,8 +10,6 @@ SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
#include "shell_integration.h"
|
||||||
|
#include "wallpaper_integration.h"
|
||||||
|
|
||||||
|
-#include "../logind.h"
|
||||||
|
-
|
||||||
|
#include <config-kscreenlocker.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <unistd.h>
|
||||||
|
@@ -133,7 +131,6 @@ UnlockApp::UnlockApp(int &argc, char **argv)
|
||||||
|
, m_graceTime(0)
|
||||||
|
, m_noLock(false)
|
||||||
|
, m_shellIntegration(new ShellIntegration(this))
|
||||||
|
- , m_logindIntegration(new LogindIntegration(this))
|
||||||
|
{
|
||||||
|
auto interactive = std::make_unique<PamAuthenticator>(QStringLiteral(KSCREENLOCKER_PAM_SERVICE), KUser().loginName());
|
||||||
|
std::vector<std::unique_ptr<PamAuthenticator>> noninteractive;
|
||||||
|
@@ -142,9 +139,6 @@ UnlockApp::UnlockApp(int &argc, char **argv)
|
||||||
|
noninteractive.push_back(
|
||||||
|
std::make_unique<PamAuthenticator>(QStringLiteral(KSCREENLOCKER_PAM_SMARTCARD_SERVICE), KUser().loginName(), PamAuthenticator::Smartcard));
|
||||||
|
m_authenticators = new PamAuthenticators(std::move(interactive), std::move(noninteractive), this);
|
||||||
|
- connect(m_logindIntegration, &LogindIntegration::prepareForSleep, m_authenticators, [this] {
|
||||||
|
- m_authenticators->cancel();
|
||||||
|
- });
|
||||||
|
initialize();
|
||||||
|
|
||||||
|
if (KWindowSystem::isPlatformX11()) {
|
||||||
|
diff --git a/greeter/greeterapp.h b/greeter/greeterapp.h
|
||||||
|
index 2362dd2..ff355de 100644
|
||||||
|
--- a/greeter/greeterapp.h
|
||||||
|
+++ b/greeter/greeterapp.h
|
||||||
|
@@ -25,7 +25,6 @@ class QuickViewSharedEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Authenticator;
|
||||||
|
-class LogindIntegration;
|
||||||
|
|
||||||
|
struct org_kde_ksld;
|
||||||
|
|
||||||
|
@@ -94,6 +93,5 @@ private:
|
||||||
|
|
||||||
|
KPackage::Package m_wallpaperPackage;
|
||||||
|
ShellIntegration *m_shellIntegration;
|
||||||
|
- LogindIntegration *m_logindIntegration;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
From: Anton Partanen
|
||||||
|
Subject: [PATCH] Allow retrying non-interactive authentication
|
||||||
|
|
||||||
|
An active password conversation should not prevent a completed fingerprint
|
||||||
|
conversation from being started again. PamAuthenticator::tryUnlock() already
|
||||||
|
ignores authenticators that are still running, so let subsequent start
|
||||||
|
requests reach each authenticator.
|
||||||
|
|
||||||
|
This is a minimal backport of the state-guard removal in upstream commit
|
||||||
|
a5ed9ca0. It allows a fingerprint attempt interrupted by suspend to restart
|
||||||
|
without cancelling the password conversation.
|
||||||
|
---
|
||||||
|
greeter/pamauthenticators.cpp | 2 +-
|
||||||
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/greeter/pamauthenticators.cpp b/greeter/pamauthenticators.cpp
|
||||||
|
index 7c53b73..f60516d 100644
|
||||||
|
--- a/greeter/pamauthenticators.cpp
|
||||||
|
+++ b/greeter/pamauthenticators.cpp
|
||||||
|
@@ -141,7 +141,7 @@ PamAuthenticators::AuthenticatorsState PamAuthenticators::state() const
|
||||||
|
|
||||||
|
void PamAuthenticators::startAuthenticating()
|
||||||
|
{
|
||||||
|
- if (d->state == AuthenticatorsState::Authenticating || d->graceLocked) {
|
||||||
|
+ if (d->graceLocked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
From: Anton Partanen
|
||||||
|
Subject: [PATCH] Allow retry after transient authentication unavailability
|
||||||
|
|
||||||
|
PAM_AUTHINFO_UNAVAIL is not necessarily permanent. In particular,
|
||||||
|
pam_fprintd returns it when an active verification is interrupted by system
|
||||||
|
suspend. Treat that result as a failed attempt so a later start request can
|
||||||
|
retry it. Continue to cache PAM_MODULE_UNKNOWN as permanent unavailability.
|
||||||
|
---
|
||||||
|
greeter/pamauthenticator.cpp | 4 +++-
|
||||||
|
1 file changed, 3 insertions(+), 1 deletion(-)
|
||||||
|
|
||||||
|
diff --git a/greeter/pamauthenticator.cpp b/greeter/pamauthenticator.cpp
|
||||||
|
index e2011fd..bb2521f 100644
|
||||||
|
--- a/greeter/pamauthenticator.cpp
|
||||||
|
+++ b/greeter/pamauthenticator.cpp
|
||||||
|
@@ -176,7 +176,9 @@ void PamWorker::authenticate()
|
||||||
|
pam_setcred(m_handle, PAM_REFRESH_CRED);
|
||||||
|
/* ignore errors on refresh credentials. If this did not work we use the old ones. */
|
||||||
|
Q_EMIT succeeded();
|
||||||
|
- } else if (rc == PAM_AUTHINFO_UNAVAIL || rc == PAM_MODULE_UNKNOWN) {
|
||||||
|
+ } else if (rc == PAM_AUTHINFO_UNAVAIL) {
|
||||||
|
+ Q_EMIT failed();
|
||||||
|
+ } else if (rc == PAM_MODULE_UNKNOWN) {
|
||||||
|
m_unavailable = true;
|
||||||
|
Q_EMIT unavailabilityChanged(m_unavailable);
|
||||||
|
} else {
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
From: Anton Partanen
|
||||||
|
Subject: [PATCH] Retry transient unavailability for fingerprint only
|
||||||
|
|
||||||
|
Other non-interactive authenticators, notably smartcards, also use
|
||||||
|
PAM_AUTHINFO_UNAVAIL to report that no credential is present. Restrict the
|
||||||
|
retry behavior to fingerprint authenticators so absent smartcards remain
|
||||||
|
unavailable instead of repeatedly flashing in the UI.
|
||||||
|
---
|
||||||
|
greeter/pamauthenticator.cpp | 12 +++++++-----
|
||||||
|
1 file changed, 7 insertions(+), 5 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/greeter/pamauthenticator.cpp b/greeter/pamauthenticator.cpp
|
||||||
|
index bb2521f..e27e61c 100644
|
||||||
|
--- a/greeter/pamauthenticator.cpp
|
||||||
|
+++ b/greeter/pamauthenticator.cpp
|
||||||
|
@@ -27,7 +27,7 @@ class PamWorker : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
- PamWorker();
|
||||||
|
+ explicit PamWorker(bool retryOnAuthInfoUnavailable);
|
||||||
|
~PamWorker() override;
|
||||||
|
Q_DISABLE_COPY_MOVE(PamWorker)
|
||||||
|
void start(const QString &service, const QString &user);
|
||||||
|
@@ -52,6 +52,7 @@ private:
|
||||||
|
bool m_unavailable = false;
|
||||||
|
bool m_inAuthenticate = false;
|
||||||
|
std::chrono::steady_clock::time_point m_nextAttemptAllowedTime;
|
||||||
|
+ const bool m_retryOnAuthInfoUnavailable;
|
||||||
|
int m_result = -1;
|
||||||
|
QString m_service;
|
||||||
|
};
|
||||||
|
@@ -163,10 +164,11 @@ int PamWorker::converse(int n, const struct pam_message **msg, struct pam_respons
|
||||||
|
return PAM_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
-PamWorker::PamWorker()
|
||||||
|
+PamWorker::PamWorker(bool retryOnAuthInfoUnavailable)
|
||||||
|
: QObject(nullptr)
|
||||||
|
, m_conv({&PamWorker::converse, this})
|
||||||
|
, m_nextAttemptAllowedTime(std::chrono::steady_clock::now())
|
||||||
|
+ , m_retryOnAuthInfoUnavailable(retryOnAuthInfoUnavailable)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -176,9 +178,9 @@ void PamWorker::authenticate()
|
||||||
|
pam_setcred(m_handle, PAM_REFRESH_CRED);
|
||||||
|
/* ignore errors on refresh credentials. If this did not work we use the old ones. */
|
||||||
|
Q_EMIT succeeded();
|
||||||
|
- } else if (rc == PAM_AUTHINFO_UNAVAIL) {
|
||||||
|
+ } else if (rc == PAM_AUTHINFO_UNAVAIL && m_retryOnAuthInfoUnavailable) {
|
||||||
|
Q_EMIT failed();
|
||||||
|
- } else if (rc == PAM_MODULE_UNKNOWN) {
|
||||||
|
+ } else if (rc == PAM_AUTHINFO_UNAVAIL || rc == PAM_MODULE_UNKNOWN) {
|
||||||
|
m_unavailable = true;
|
||||||
|
Q_EMIT unavailabilityChanged(m_unavailable);
|
||||||
|
} else {
|
||||||
|
@@ -268,7 +271,7 @@ PamAuthenticator::PamAuthenticator(const QString &service, const QString &user, N
|
||||||
|
})
|
||||||
|
, m_service(service)
|
||||||
|
, m_authenticatorType(types)
|
||||||
|
- , d(new PamWorker)
|
||||||
|
+ , d(new PamWorker(types.testFlag(NoninteractiveAuthenticatorType::Fingerprint)))
|
||||||
|
{
|
||||||
|
d->moveToThread(&m_thread);
|
||||||
|
|
||||||
|
--
|
||||||
|
2.51.0
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
[ "$1" = post ] || exit 0
|
||||||
|
systemctl --quiet is-active fprintd.service || exit 0
|
||||||
|
|
||||||
|
systemctl --no-block restart fprintd.service
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
payload_url=https://git.ajpanton.se/api/packages/ajp_anton/generic/plasma-fingerprint-workaround/6.7.4-1.fc44.ajp5/kscreenlocker-6.7.4-1.fc44.ajp5.x86_64.rpm
|
||||||
|
payload_sha256=d64515f3c7cb9c44b1c8fc194e90503be5944b1d24094aab2f68d989b3eca381
|
||||||
+306
@@ -0,0 +1,306 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PATH=/usr/sbin:/usr/bin
|
||||||
|
readonly data_dir=/usr/share/plasma-fingerprint-workaround
|
||||||
|
readonly payload_config="$data_dir/payload.conf"
|
||||||
|
readonly program=${0##*/}
|
||||||
|
temporary_dir=
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage:
|
||||||
|
$program status
|
||||||
|
$program enable [--rpm PATH] [--force] [--yes]
|
||||||
|
$program disable [--yes]
|
||||||
|
|
||||||
|
Without --rpm, enable downloads the tested prebuilt package. A local package
|
||||||
|
must have been built from this tool's KScreenLocker spec. --force permits a
|
||||||
|
base-version mismatch, including an intentional downgrade.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
die() {
|
||||||
|
printf 'Error: %s\n' "$*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
require_root() {
|
||||||
|
(( EUID == 0 )) || die "run this command as root"
|
||||||
|
}
|
||||||
|
|
||||||
|
require_fedora() {
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source /etc/os-release
|
||||||
|
[[ ${ID:-} == fedora ]] || die "this workaround only supports Fedora Linux"
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
[[ -n $temporary_dir ]] || return
|
||||||
|
rm -f -- "$temporary_dir/kscreenlocker.rpm"
|
||||||
|
rmdir -- "$temporary_dir"
|
||||||
|
}
|
||||||
|
|
||||||
|
package_value() {
|
||||||
|
local mode=$1
|
||||||
|
local format=$2
|
||||||
|
local package=$3
|
||||||
|
|
||||||
|
rpm "$mode" --qf "$format" -- "$package"
|
||||||
|
}
|
||||||
|
|
||||||
|
package_base() {
|
||||||
|
local mode=$1
|
||||||
|
local package=$2
|
||||||
|
local provides
|
||||||
|
|
||||||
|
provides=$(rpm "$mode" --provides -- "$package")
|
||||||
|
sed -n 's/^plasma-fingerprint-workaround-base = //p' <<<"$provides"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_workaround_package() {
|
||||||
|
local mode=$1
|
||||||
|
local package=$2
|
||||||
|
local provides
|
||||||
|
|
||||||
|
provides=$(rpm "$mode" --provides -- "$package")
|
||||||
|
grep -qx 'plasma-fingerprint-workaround-payload = 1' <<<"$provides"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_legacy_workaround() {
|
||||||
|
[[ $(installed_value '%{RELEASE}') =~ \.ajp[[:digit:]]+$ ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_any_workaround() {
|
||||||
|
is_workaround_package -q kscreenlocker || is_legacy_workaround
|
||||||
|
}
|
||||||
|
|
||||||
|
installed_value() {
|
||||||
|
package_value -q "$1" kscreenlocker
|
||||||
|
}
|
||||||
|
|
||||||
|
installed_base() {
|
||||||
|
local base
|
||||||
|
|
||||||
|
base=$(package_base -q kscreenlocker)
|
||||||
|
if [[ -n $base ]]; then
|
||||||
|
printf '%s\n' "$base"
|
||||||
|
elif is_legacy_workaround; then
|
||||||
|
printf '%s-%s\n' \
|
||||||
|
"$(installed_value '%{VERSION}')" \
|
||||||
|
"$(installed_value '%{RELEASE}' | sed 's/\.ajp[[:digit:]]*$//')"
|
||||||
|
else
|
||||||
|
installed_value '%{EVR}'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
show_status() {
|
||||||
|
if ! rpm -q kscreenlocker >/dev/null 2>&1; then
|
||||||
|
printf 'KScreenLocker is not installed.\n'
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if is_workaround_package -q kscreenlocker; then
|
||||||
|
printf 'Fingerprint workaround: enabled\n'
|
||||||
|
printf 'Installed package: kscreenlocker-%s.%s\n' \
|
||||||
|
"$(installed_value '%{EVR}')" "$(installed_value '%{ARCH}')"
|
||||||
|
printf 'Based on Fedora package: kscreenlocker-%s\n' "$(installed_base)"
|
||||||
|
elif is_legacy_workaround; then
|
||||||
|
printf 'Fingerprint workaround: enabled (legacy unmanaged build)\n'
|
||||||
|
printf 'Installed package: kscreenlocker-%s.%s\n' \
|
||||||
|
"$(installed_value '%{EVR}')" "$(installed_value '%{ARCH}')"
|
||||||
|
printf 'Based on Fedora package: kscreenlocker-%s\n' "$(installed_base)"
|
||||||
|
else
|
||||||
|
printf 'Fingerprint workaround: disabled\n'
|
||||||
|
printf 'Installed package: kscreenlocker-%s.%s\n' \
|
||||||
|
"$(installed_value '%{EVR}')" "$(installed_value '%{ARCH}')"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm() {
|
||||||
|
local answer
|
||||||
|
|
||||||
|
if (( assume_yes )); then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'Continue? [y/N] '
|
||||||
|
read -r answer || exit 0
|
||||||
|
[[ $answer == y || $answer == Y ]] || exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
load_payload_config() {
|
||||||
|
[[ -r $payload_config ]] || die "payload configuration is missing"
|
||||||
|
|
||||||
|
unset payload_url payload_sha256
|
||||||
|
# This root-owned file is installed by the controller RPM.
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$payload_config"
|
||||||
|
|
||||||
|
[[ ${payload_url:-} == https://* ]] || die "invalid payload URL"
|
||||||
|
[[ ${payload_sha256:-} =~ ^[[:xdigit:]]{64}$ ]] ||
|
||||||
|
die "invalid payload checksum"
|
||||||
|
}
|
||||||
|
|
||||||
|
validate_candidate() {
|
||||||
|
local candidate=$1
|
||||||
|
local name arch candidate_evr candidate_base current_base current_evr
|
||||||
|
|
||||||
|
rpm -K --nosignature "$candidate" >/dev/null || die "the RPM is corrupt"
|
||||||
|
|
||||||
|
name=$(package_value -qp '%{NAME}' "$candidate")
|
||||||
|
[[ $name == kscreenlocker ]] ||
|
||||||
|
die "expected a kscreenlocker RPM, got $name"
|
||||||
|
|
||||||
|
is_workaround_package -qp "$candidate" ||
|
||||||
|
die "the RPM was not built from this workaround's KScreenLocker spec"
|
||||||
|
|
||||||
|
arch=$(package_value -qp '%{ARCH}' "$candidate")
|
||||||
|
[[ $arch == "$(installed_value '%{ARCH}')" ]] ||
|
||||||
|
die "RPM architecture $arch does not match installed architecture $(installed_value '%{ARCH}')"
|
||||||
|
|
||||||
|
candidate_base=$(package_base -qp "$candidate")
|
||||||
|
[[ -n $candidate_base ]] || die "the RPM has no base-version marker"
|
||||||
|
|
||||||
|
candidate_evr=$(package_value -qp '%{EVR}' "$candidate")
|
||||||
|
current_base=$(installed_base)
|
||||||
|
current_evr=$(installed_value '%{EVR}')
|
||||||
|
|
||||||
|
printf 'Installed: kscreenlocker-%s\n' "$current_evr"
|
||||||
|
printf 'Candidate: kscreenlocker-%s (based on %s)\n' \
|
||||||
|
"$candidate_evr" "$candidate_base"
|
||||||
|
|
||||||
|
if [[ $candidate_base != "$current_base" ]]; then
|
||||||
|
if (( ! force )); then
|
||||||
|
die "candidate base $candidate_base does not match installed base $current_base; use --force to allow the version change"
|
||||||
|
fi
|
||||||
|
printf 'Warning: forcing a KScreenLocker base-version change.\n' >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
enable_workaround() {
|
||||||
|
local rpm_path='' candidate
|
||||||
|
local -a dnf_args
|
||||||
|
|
||||||
|
force=0
|
||||||
|
assume_yes=0
|
||||||
|
while (( $# )); do
|
||||||
|
case $1 in
|
||||||
|
--rpm)
|
||||||
|
(( $# >= 2 )) || die "--rpm requires a path"
|
||||||
|
rpm_path=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
--force)
|
||||||
|
force=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--yes)
|
||||||
|
assume_yes=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "unknown enable option: $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
require_root
|
||||||
|
require_fedora
|
||||||
|
rpm -q kscreenlocker >/dev/null 2>&1 || die "KScreenLocker is not installed"
|
||||||
|
|
||||||
|
umask 077
|
||||||
|
temporary_dir=$(mktemp -d /var/tmp/plasma-fingerprint-workaround.XXXXXX)
|
||||||
|
trap cleanup EXIT
|
||||||
|
candidate="$temporary_dir/kscreenlocker.rpm"
|
||||||
|
|
||||||
|
if [[ -n $rpm_path ]]; then
|
||||||
|
[[ -f $rpm_path ]] || die "RPM not found: $rpm_path"
|
||||||
|
install -m 0600 -- "$rpm_path" "$candidate"
|
||||||
|
else
|
||||||
|
load_payload_config
|
||||||
|
printf 'Downloading the tested KScreenLocker build...\n'
|
||||||
|
curl --fail --location --show-error --silent \
|
||||||
|
--proto '=https' --proto-redir '=https' \
|
||||||
|
--output "$candidate" "$payload_url"
|
||||||
|
printf '%s %s\n' "$payload_sha256" "$candidate" |
|
||||||
|
sha256sum --check --status - || die "downloaded RPM checksum does not match"
|
||||||
|
fi
|
||||||
|
|
||||||
|
validate_candidate "$candidate"
|
||||||
|
printf '\nThis replaces Fedora\x27s security-sensitive KScreenLocker package.\n'
|
||||||
|
confirm
|
||||||
|
|
||||||
|
dnf_args=(install --assumeyes)
|
||||||
|
(( force )) && dnf_args+=(--allow-downgrade)
|
||||||
|
dnf5 "${dnf_args[@]}" "$candidate"
|
||||||
|
|
||||||
|
is_workaround_package -q kscreenlocker ||
|
||||||
|
die "DNF completed without enabling the workaround"
|
||||||
|
printf 'Fingerprint workaround enabled. Reboot before testing it.\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
disable_workaround() {
|
||||||
|
assume_yes=0
|
||||||
|
while (( $# )); do
|
||||||
|
case $1 in
|
||||||
|
--yes)
|
||||||
|
assume_yes=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
die "unknown disable option: $1"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
require_root
|
||||||
|
require_fedora
|
||||||
|
if ! is_any_workaround; then
|
||||||
|
printf 'Fingerprint workaround is already disabled.\n'
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'This will replace the workaround with Fedora\x27s current KScreenLocker package.\n'
|
||||||
|
confirm
|
||||||
|
|
||||||
|
dnf5 \
|
||||||
|
--repo=fedora,updates \
|
||||||
|
--refresh \
|
||||||
|
distro-sync \
|
||||||
|
--assumeyes \
|
||||||
|
kscreenlocker
|
||||||
|
|
||||||
|
if is_any_workaround; then
|
||||||
|
die "no suitable Fedora KScreenLocker package was installed"
|
||||||
|
fi
|
||||||
|
printf 'Fingerprint workaround disabled. Reboot before testing the lock screen.\n'
|
||||||
|
}
|
||||||
|
|
||||||
|
command=${1:-}
|
||||||
|
[[ -n $command ]] || {
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
shift
|
||||||
|
|
||||||
|
case $command in
|
||||||
|
status)
|
||||||
|
(( $# == 0 )) || die "status takes no options"
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
enable)
|
||||||
|
enable_workaround "$@"
|
||||||
|
;;
|
||||||
|
disable)
|
||||||
|
disable_workaround "$@"
|
||||||
|
;;
|
||||||
|
-h|--help|help)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
Name: plasma-fingerprint-workaround
|
||||||
|
Version: 0.1.0
|
||||||
|
Release: 1%{?dist}
|
||||||
|
Summary: Opt-in installer for a patched Fedora KScreenLocker
|
||||||
|
|
||||||
|
License: MIT
|
||||||
|
URL: https://git.ajpanton.se/ajp_anton/fedora-tools
|
||||||
|
Source0: plasma-fingerprint-workaround
|
||||||
|
Source1: payload.conf
|
||||||
|
Source2: LICENSE
|
||||||
|
Source3: README.md
|
||||||
|
Source4: test-controller
|
||||||
|
|
||||||
|
BuildArch: noarch
|
||||||
|
BuildRequires: bash
|
||||||
|
BuildRequires: grep
|
||||||
|
Requires: bash
|
||||||
|
Requires: coreutils
|
||||||
|
Requires: curl
|
||||||
|
Requires: dnf5
|
||||||
|
Requires: grep
|
||||||
|
Requires: rpm
|
||||||
|
Requires: sed
|
||||||
|
|
||||||
|
%description
|
||||||
|
Provides an explicit, reversible installer for an experimental KScreenLocker
|
||||||
|
fingerprint workaround. Installing this package alone makes no system changes.
|
||||||
|
|
||||||
|
%prep
|
||||||
|
|
||||||
|
%build
|
||||||
|
|
||||||
|
%check
|
||||||
|
bash %{SOURCE4} %{SOURCE0} %{SOURCE1}
|
||||||
|
|
||||||
|
%install
|
||||||
|
install -D -m 0755 %{SOURCE0} \
|
||||||
|
%{buildroot}%{_bindir}/plasma-fingerprint-workaround
|
||||||
|
install -D -m 0644 %{SOURCE1} \
|
||||||
|
%{buildroot}%{_datadir}/plasma-fingerprint-workaround/payload.conf
|
||||||
|
install -D -m 0644 %{SOURCE2} \
|
||||||
|
%{buildroot}%{_licensedir}/%{name}/LICENSE
|
||||||
|
install -D -m 0644 %{SOURCE3} \
|
||||||
|
%{buildroot}%{_docdir}/%{name}/README.md
|
||||||
|
|
||||||
|
%files
|
||||||
|
%license %{_licensedir}/%{name}/LICENSE
|
||||||
|
%doc %{_docdir}/%{name}/README.md
|
||||||
|
%{_bindir}/plasma-fingerprint-workaround
|
||||||
|
%{_datadir}/plasma-fingerprint-workaround/payload.conf
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Fri Sep 04 2026 Anton - 0.1.0-1
|
||||||
|
- Initial package
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
controller=$1
|
||||||
|
payload_config=$2
|
||||||
|
|
||||||
|
bash -n "$controller"
|
||||||
|
"$controller" --help | grep -q '^ .* enable \[--rpm PATH\] \[--force\] \[--yes\]$'
|
||||||
|
|
||||||
|
if "$controller" unknown-command >/dev/null 2>&1; then
|
||||||
|
printf 'Unknown command unexpectedly succeeded.\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
payload_url=
|
||||||
|
payload_sha256=
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$payload_config"
|
||||||
|
[[ $payload_url == https://*/*.rpm ]]
|
||||||
|
[[ $payload_sha256 =~ ^[[:xdigit:]]{64}$ ]]
|
||||||
|
|
||||||
|
printf 'Controller tests passed.\n'
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
rpm_path=$1
|
||||||
|
expected_base=$2
|
||||||
|
provides=$(rpm -qp --provides "$rpm_path")
|
||||||
|
files=$(rpm -qpl "$rpm_path")
|
||||||
|
|
||||||
|
rpm -K --nosignature "$rpm_path" >/dev/null
|
||||||
|
[[ $(rpm -qp --qf '%{NAME}' "$rpm_path") == kscreenlocker ]]
|
||||||
|
grep -qx 'plasma-fingerprint-workaround-payload = 1' <<<"$provides"
|
||||||
|
grep -qx "plasma-fingerprint-workaround-base = $expected_base" <<<"$provides"
|
||||||
|
grep -qx '/usr/lib/systemd/system-sleep/restart-fprintd-after-resume' <<<"$files"
|
||||||
|
|
||||||
|
printf 'Patched KScreenLocker package tests passed.\n'
|
||||||
Executable
+60
@@ -0,0 +1,60 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||||
|
source_dir="$repo_root/plasma-fingerprint-workaround/kscreenlocker"
|
||||||
|
topdir="$repo_root/rpmbuild"
|
||||||
|
version=${KSCREENLOCKER_VERSION:-6.7.4}
|
||||||
|
base_release=${KSCREENLOCKER_BASE_RELEASE:-1}
|
||||||
|
workaround_release=${KSCREENLOCKER_WORKAROUND_RELEASE:-5}
|
||||||
|
archive="$topdir/SOURCES/kscreenlocker-$version.tar.xz"
|
||||||
|
archive_url="https://download.kde.org/stable/plasma/$version/kscreenlocker-$version.tar.xz"
|
||||||
|
|
||||||
|
if [[ $version == 6.7.4 ]]; then
|
||||||
|
default_archive_sha256=f9cd525d501f08931f2c0b4d08f5384588967bc89fac62e39ed4ae2da2925a39
|
||||||
|
else
|
||||||
|
default_archive_sha256=
|
||||||
|
fi
|
||||||
|
archive_sha256=${KSCREENLOCKER_SOURCE_SHA256:-$default_archive_sha256}
|
||||||
|
if [[ ! $archive_sha256 =~ ^[[:xdigit:]]{64}$ ]]; then
|
||||||
|
printf 'Error: set KSCREENLOCKER_SOURCE_SHA256 for KScreenLocker %s.\n' \
|
||||||
|
"$version" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$topdir"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
|
|
||||||
|
if [[ ! -f $archive ]]; then
|
||||||
|
temporary_archive="$archive.download"
|
||||||
|
trap 'rm -f -- "$temporary_archive"' EXIT
|
||||||
|
curl --fail --location --show-error \
|
||||||
|
--proto '=https' --proto-redir '=https' \
|
||||||
|
--output "$temporary_archive" "$archive_url"
|
||||||
|
mv -- "$temporary_archive" "$archive"
|
||||||
|
trap - EXIT
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf '%s %s\n' "$archive_sha256" "$archive" |
|
||||||
|
sha256sum --check --status - || {
|
||||||
|
printf 'Error: KScreenLocker source archive checksum does not match.\n' >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
for patch in "$source_dir"/patches/*.patch; do
|
||||||
|
install -m 0644 "$patch" "$topdir/SOURCES/${patch##*/}"
|
||||||
|
done
|
||||||
|
install -m 0755 \
|
||||||
|
"$source_dir/restart-fprintd-after-resume" \
|
||||||
|
"$topdir/SOURCES/restart-fprintd-after-resume"
|
||||||
|
|
||||||
|
rpmbuild \
|
||||||
|
--define "_topdir $topdir" \
|
||||||
|
--define "upstream_version $version" \
|
||||||
|
--define "base_release $base_release" \
|
||||||
|
--define "workaround_release $workaround_release" \
|
||||||
|
-ba "$source_dir/kscreenlocker.spec"
|
||||||
|
|
||||||
|
rpm_path="$topdir/RPMS/$(rpm --eval '%{_arch}')/kscreenlocker-$version-$base_release$(rpm --eval '%{?dist}').ajp$workaround_release.$(rpm --eval '%{_arch}').rpm"
|
||||||
|
bash "$repo_root/plasma-fingerprint-workaround/tests/test-patched-kscreenlocker-rpm" \
|
||||||
|
"$rpm_path" "$version-$base_release$(rpm --eval '%{?dist}')"
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repo_root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||||
|
tool_dir="$repo_root/plasma-fingerprint-workaround"
|
||||||
|
topdir="$repo_root/rpmbuild"
|
||||||
|
|
||||||
|
mkdir -p "$topdir"/{BUILD,BUILDROOT,RPMS,SOURCES,SPECS,SRPMS}
|
||||||
|
install -m 0755 \
|
||||||
|
"$tool_dir/plasma-fingerprint-workaround" \
|
||||||
|
"$topdir/SOURCES/plasma-fingerprint-workaround"
|
||||||
|
install -m 0644 "$tool_dir/payload.conf" "$topdir/SOURCES/payload.conf"
|
||||||
|
install -m 0644 "$repo_root/LICENSE" "$topdir/SOURCES/LICENSE"
|
||||||
|
install -m 0644 "$tool_dir/README.md" "$topdir/SOURCES/README.md"
|
||||||
|
install -m 0755 "$tool_dir/tests/test-controller" "$topdir/SOURCES/test-controller"
|
||||||
|
|
||||||
|
rpmbuild \
|
||||||
|
--define "_topdir $topdir" \
|
||||||
|
-bb "$tool_dir/plasma-fingerprint-workaround.spec"
|
||||||
+53
@@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
printf 'Usage: GITEA_TOKEN=... %s PATH_TO_RPM\n' "$0" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
if (( $# != 1 )); then
|
||||||
|
usage
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
repo_root=$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")/.." && pwd)
|
||||||
|
payload_config="$repo_root/plasma-fingerprint-workaround/payload.conf"
|
||||||
|
rpm_path=$1
|
||||||
|
|
||||||
|
if [[ ! -f $rpm_path || $rpm_path != *.rpm ]]; then
|
||||||
|
printf 'Error: %s is not an RPM file.\n' "$rpm_path" >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z ${GITEA_TOKEN:-} ]]; then
|
||||||
|
printf 'Error: set GITEA_TOKEN to a Gitea access token with package write permission.\n' >&2
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
payload_url=
|
||||||
|
payload_sha256=
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
source "$payload_config"
|
||||||
|
|
||||||
|
actual_sha256=$(sha256sum "$rpm_path")
|
||||||
|
actual_sha256=${actual_sha256%% *}
|
||||||
|
if [[ $actual_sha256 != "$payload_sha256" ]]; then
|
||||||
|
printf 'Error: RPM checksum does not match payload.conf.\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ${rpm_path##*/} != "${payload_url##*/}" ]]; then
|
||||||
|
printf 'Error: RPM filename does not match payload.conf.\n' >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
curl \
|
||||||
|
--fail-with-body \
|
||||||
|
--show-error \
|
||||||
|
--silent \
|
||||||
|
--user "ajp_anton:${GITEA_TOKEN}" \
|
||||||
|
--upload-file "$rpm_path" \
|
||||||
|
"$payload_url"
|
||||||
|
|
||||||
|
printf 'Published %s as a generic Gitea package.\n' "$rpm_path"
|
||||||
Reference in New Issue
Block a user