mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-08-02 03:28:28 -04:00
fix(greeter): reimplement regression to hide debug logs during login
- Provide more status feedback
- Allow 2 fprint tries within 10 seconds for DMS-managed PAM
- Updated dms greeter docs
Note: distro-managed PAM takes precedence and may use different limits.
DMS auth changes remain conditional on greetd being installed.
Fixes #2853
Port 1.5
(cherry picked from commit 5b41d699fa)
This commit is contained in:
@@ -476,7 +476,7 @@ Singleton {
|
||||
if (exitCode === 0)
|
||||
return "missing_enrollment";
|
||||
if (exitCode === 127 || (output || "").includes("__missing_command__"))
|
||||
return "probe_failed";
|
||||
return "missing_pam_support";
|
||||
return pamFprintDetected ? "probe_failed" : "missing_pam_support";
|
||||
}
|
||||
|
||||
|
||||
@@ -153,12 +153,10 @@ Singleton {
|
||||
blockWrites: true
|
||||
atomicWrites: false
|
||||
watchChanges: false
|
||||
printErrors: true
|
||||
printErrors: false
|
||||
onLoaded: {
|
||||
parseSessionConfig(sessionConfigFileView.text());
|
||||
}
|
||||
onLoadFailed: error => {
|
||||
log.warn("Could not load greeter session config from", root.sessionConfigPath, "error:", error);
|
||||
}
|
||||
onLoadFailed: {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,12 +219,11 @@ Singleton {
|
||||
blockWrites: true
|
||||
atomicWrites: false
|
||||
watchChanges: false
|
||||
printErrors: true
|
||||
printErrors: false
|
||||
onLoaded: {
|
||||
parseSettings(settingsFile.text());
|
||||
}
|
||||
onLoadFailed: error => {
|
||||
log.warn("Failed to load greetd settings:", error);
|
||||
onLoadFailed: {
|
||||
root.parseSettings("");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ Item {
|
||||
property int passwordFailureCount: 0
|
||||
property int passwordAttemptLimitHint: 0
|
||||
property string authFeedbackMessage: ""
|
||||
property string authSuccessMessage: ""
|
||||
property string greetdPamText: ""
|
||||
property string systemAuthPamText: ""
|
||||
property string commonAuthPamText: ""
|
||||
@@ -67,11 +68,23 @@ Item {
|
||||
property bool fprintdProbeComplete: false
|
||||
property bool fprintdHasDevice: false
|
||||
property bool autoLoginOnSuccess: false
|
||||
readonly property bool greeterPamStackHasFprint: greeterPamStackHasModule("pam_fprintd")
|
||||
// Falls back to PAM-only detection until the fprintd D-Bus probe completes.
|
||||
readonly property bool greeterPamHasFprint: greeterPamStackHasModule("pam_fprintd") && (!fprintdProbeComplete || fprintdHasDevice)
|
||||
readonly property bool greeterPamHasFprint: greeterPamStackHasFprint && (!fprintdProbeComplete || fprintdHasDevice)
|
||||
readonly property bool greeterPamHasU2f: greeterPamStackHasModule("pam_u2f")
|
||||
readonly property bool greeterExternalAuthAvailable: (greeterPamHasFprint && GreetdSettings.greeterEnableFprint) || (greeterPamHasU2f && GreetdSettings.greeterEnableU2f)
|
||||
readonly property bool greeterPamHasExternalAuth: greeterPamHasFprint || greeterPamHasU2f
|
||||
readonly property bool greeterPamHasExternalAuth: greeterPamStackHasFprint || greeterPamHasU2f
|
||||
readonly property bool externalAuthInProgress: awaitingExternalAuth || (Greetd.state !== GreetdState.Inactive && passwordSubmitRequested && greeterPamHasExternalAuth && !pendingPasswordResponse)
|
||||
readonly property string externalAuthStatusMessage: {
|
||||
if (!externalAuthInProgress)
|
||||
return "";
|
||||
if (greeterPamStackHasFprint && greeterPamHasU2f)
|
||||
return I18n.tr("Awaiting fingerprint or security key authentication");
|
||||
if (greeterPamStackHasFprint)
|
||||
return I18n.tr("Awaiting fingerprint authentication");
|
||||
return I18n.tr("Awaiting security key authentication");
|
||||
}
|
||||
readonly property string authDisplayMessage: authFeedbackMessage || authSuccessMessage || externalAuthStatusMessage
|
||||
readonly property bool autoLoginAvailable: GreetdSettings.rememberLastUser && GreetdSettings.rememberLastSession
|
||||
readonly property bool multipleUsersAvailable: GreeterUsersService.loaded && GreeterUsersService.users.length > 1
|
||||
// Single-user systems get the picker too when auto-login is available, so the
|
||||
@@ -238,7 +251,7 @@ Item {
|
||||
|
||||
function isLikelyLockoutMessage(message) {
|
||||
const lower = (message || "").toLowerCase();
|
||||
return lower.includes("account is locked") || lower.includes("too many") || lower.includes("maximum number of") || lower.includes("auth_err");
|
||||
return lower.includes("account is locked") || lower.includes("too many") || lower.includes("maximum number of");
|
||||
}
|
||||
|
||||
function currentAuthMessage() {
|
||||
@@ -251,11 +264,11 @@ Item {
|
||||
const attempt = Math.max(1, Math.min(passwordFailureCount, passwordAttemptLimitHint));
|
||||
const remaining = Math.max(passwordAttemptLimitHint - attempt, 0);
|
||||
if (remaining > 0) {
|
||||
return I18n.tr("Incorrect password - attempt %1 of %2 (lockout may follow)").arg(attempt).arg(passwordAttemptLimitHint);
|
||||
return I18n.tr("Authentication failed - attempt %1 of %2").arg(attempt).arg(passwordAttemptLimitHint);
|
||||
}
|
||||
return I18n.tr("Incorrect password - next failures may trigger account lockout");
|
||||
return I18n.tr("Authentication failed - lockout can occur");
|
||||
}
|
||||
return I18n.tr("Incorrect password");
|
||||
return I18n.tr("Authentication failed - try again");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
@@ -263,6 +276,7 @@ Item {
|
||||
function clearAuthFeedback() {
|
||||
GreeterState.pamState = "";
|
||||
authFeedbackMessage = "";
|
||||
authSuccessMessage = "";
|
||||
}
|
||||
|
||||
function resetPasswordSessionTransition(clearSubmitRequest) {
|
||||
@@ -619,8 +633,8 @@ Item {
|
||||
pendingPasswordResponse = false;
|
||||
passwordSubmitRequested = submitPassword;
|
||||
awaitingExternalAuth = !submitPassword && !hasPasswordBuffer && root.greeterExternalAuthAvailable;
|
||||
// Use greeterExternalAuthAvailable so systems with pam_fprintd but no hardware don't incur the 30 s wait.
|
||||
const waitingOnPamExternalBeforePassword = submitPassword && root.greeterExternalAuthAvailable;
|
||||
// Let the effective PAM stack finish external authentication.
|
||||
const waitingOnPamExternalBeforePassword = submitPassword && root.greeterPamHasExternalAuth;
|
||||
authTimeout.interval = (awaitingExternalAuth || waitingOnPamExternalBeforePassword) ? externalAuthTimeoutMs : defaultAuthTimeoutMs;
|
||||
authTimeout.restart();
|
||||
Greetd.createSession(GreeterState.username);
|
||||
@@ -1406,16 +1420,16 @@ Item {
|
||||
|
||||
StyledText {
|
||||
Layout.fillWidth: true
|
||||
Layout.preferredHeight: root.authFeedbackMessage !== "" ? 38 : 0
|
||||
Layout.preferredHeight: root.authDisplayMessage !== "" ? 38 : 0
|
||||
Layout.topMargin: -Theme.spacingS
|
||||
Layout.bottomMargin: -Theme.spacingS
|
||||
text: root.authFeedbackMessage
|
||||
color: Theme.error
|
||||
text: root.authDisplayMessage
|
||||
color: root.authFeedbackMessage !== "" ? Theme.error : (root.authSuccessMessage !== "" ? Theme.success : Theme.surfaceVariantText)
|
||||
font.pixelSize: Theme.fontSizeSmall
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
wrapMode: Text.WordWrap
|
||||
maximumLineCount: 2
|
||||
opacity: root.authFeedbackMessage !== "" ? 1 : 0
|
||||
opacity: root.authDisplayMessage !== "" ? 1 : 0
|
||||
|
||||
Behavior on opacity {
|
||||
NumberAnimation {
|
||||
@@ -1975,6 +1989,7 @@ Item {
|
||||
authTimeout.stop();
|
||||
passwordFailureCount = 0;
|
||||
clearAuthFeedback();
|
||||
authSuccessMessage = I18n.tr("Authenticated - starting session");
|
||||
const sessionCmd = GreeterState.selectedSession || GreeterState.sessionExecs[GreeterState.currentSessionIndex];
|
||||
const sessionPath = GreeterState.selectedSessionPath || GreeterState.sessionPaths[GreeterState.currentSessionIndex];
|
||||
const sessionDesktopId = GreeterState.selectedSessionDesktopId || GreeterState.sessionDesktopIds[GreeterState.currentSessionIndex] || desktopIdFromPath(sessionPath);
|
||||
@@ -2055,12 +2070,8 @@ Item {
|
||||
pendingLaunchCommand = "";
|
||||
pendingLaunchEnv = [];
|
||||
const sessionArgs = sessionCommand.trim().split(/\s+/);
|
||||
const needsVoidDbusSession = Quickshell.env("DMS_VOID") === "1"
|
||||
&& !Quickshell.env("DBUS_SESSION_BUS_ADDRESS")
|
||||
&& sessionArgs[0] !== "dbus-run-session";
|
||||
const launchArgs = needsVoidDbusSession
|
||||
? ["dbus-run-session"].concat(sessionArgs)
|
||||
: sessionArgs;
|
||||
const needsVoidDbusSession = Quickshell.env("DMS_VOID") === "1" && !Quickshell.env("DBUS_SESSION_BUS_ADDRESS") && sessionArgs[0] !== "dbus-run-session";
|
||||
const launchArgs = needsVoidDbusSession ? ["dbus-run-session"].concat(sessionArgs) : sessionArgs;
|
||||
Greetd.launch(launchArgs, launchEnv);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,12 +51,44 @@ dms greeter enable
|
||||
dms greeter sync
|
||||
```
|
||||
|
||||
Fingerprint authentication is optional. Install your distribution's
|
||||
fingerprint service/client and PAM integration before enabling it. Package
|
||||
names vary by distribution; on Fedora the native stack is:
|
||||
|
||||
```bash
|
||||
sudo dnf install fprintd fprintd-pam
|
||||
fprintd-enroll
|
||||
```
|
||||
|
||||
The distro `fprintd` package normally pulls in `libfprint` automatically. After
|
||||
enrollment, enable fingerprint login in **Settings → Greeter**. The toggle
|
||||
applies the shared PAM configuration automatically, so no additional sync is
|
||||
needed after initial greeter setup. Use `dms auth sync` only to repair or apply
|
||||
authentication manually without syncing the rest of the greeter.
|
||||
|
||||
greetd tries fingerprint and password sequentially. DMS-managed PAM allows two
|
||||
scans for up to ten seconds before password fallback. Existing distro PAM
|
||||
policy takes precedence, so fallback timing can differ.
|
||||
|
||||
Verify enrollment with `fprintd-list "$USER"`; pass a token such as
|
||||
`fprintd-enroll -f right-thumb` to enroll a specific finger. Security keys
|
||||
similarly require `pam_u2f` setup and key registration before enabling the
|
||||
login toggle.
|
||||
|
||||
If `fprintd-enroll` reports **No devices available**, check the [libfprint
|
||||
supported devices list](https://fprint.freedesktop.org/supported-devices.html).
|
||||
Some Validity/Synaptics readers are not supported by the native stack,
|
||||
regardless of distribution; the
|
||||
[open-fprintd](https://github.com/uunicorn/open-fprintd) service with the
|
||||
[python-validity](https://github.com/uunicorn/python-validity) driver may work
|
||||
instead. Follow the driver's installation and firmware instructions, and do
|
||||
not run the stock `fprintd` daemon alongside its replacement.
|
||||
|
||||
#### Syncing themes (Optional)
|
||||
|
||||
To sync your wallpaper and theme with the greeter login screen, follow the manual setup below:
|
||||
|
||||
<details>
|
||||
<summary>Manual theme syncing</summary>
|
||||
##### Manual theme syncing
|
||||
|
||||
```bash
|
||||
# Add yourself to greeter group
|
||||
|
||||
@@ -88,6 +88,19 @@ is_hyprland_lua_config() {
|
||||
return 1
|
||||
}
|
||||
|
||||
clear_vt() {
|
||||
local clear_sequence=$'\033[2J\033[H\033[3J\033[?25l'
|
||||
|
||||
# Clear retained console text on the controlling VT.
|
||||
if printf '%s' "$clear_sequence" >/dev/tty 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -t 1 ]]; then
|
||||
printf '%s' "$clear_sequence"
|
||||
fi
|
||||
}
|
||||
|
||||
exec_compositor() {
|
||||
local log_tag="$1"
|
||||
shift
|
||||
@@ -96,11 +109,14 @@ exec_compositor() {
|
||||
exec "$@"
|
||||
fi
|
||||
|
||||
clear_vt
|
||||
|
||||
if command -v systemd-cat >/dev/null 2>&1; then
|
||||
exec "$@" > >(systemd-cat -t "dms-greeter/$log_tag" -p info) 2>&1
|
||||
exec "$@" > >(systemd-cat -t "dms-greeter/$log_tag" -p info 2>/dev/null) 2>&1
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
# Preserve diagnostics on systems without journald.
|
||||
exec "$@" >>"$CACHE_DIR/$log_tag.log" 2>&1
|
||||
}
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
|
||||
Reference in New Issue
Block a user