1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-04-03 20:32:07 -04:00

(greeter): Enhance external auth handling in package/DEV mode

- add PAM manager hints for logging
This commit is contained in:
purian23
2026-03-09 14:37:34 -04:00
parent 86f9cf4376
commit 713b36662c
3 changed files with 175 additions and 37 deletions

View File

@@ -1249,7 +1249,17 @@ func extractGreeterWrapperFromCommand(command string) string {
if len(tokens) == 0 {
return ""
}
return strings.Trim(tokens[0], "\"")
wrapper := strings.Trim(tokens[0], "\"")
if wrapper == "" {
return ""
}
if len(tokens) > 1 {
next := strings.Trim(tokens[1], "\"")
if next != "" && (filepath.Base(wrapper) == "bash" || filepath.Base(wrapper) == "sh") && strings.Contains(filepath.Base(next), "dms-greeter") {
return fmt.Sprintf("%s (script: %s)", wrapper, next)
}
}
return wrapper
}
func extractGreeterPathOverrideFromCommand(command string) string {
@@ -1335,6 +1345,26 @@ func packageInstallHint() string {
}
}
func systemPamManagerRemediationHint() string {
osInfo, err := distros.GetOSInfo()
if err != nil {
return "Disable it in your PAM manager (authselect/pam-auth-update) or in the included PAM stack to force password-only greeter login."
}
config, exists := distros.Registry[osInfo.Distribution.ID]
if !exists {
return "Disable it in your PAM manager (authselect/pam-auth-update) or in the included PAM stack to force password-only greeter login."
}
switch config.Family {
case distros.FamilyFedora:
return "Disable it in authselect to force password-only greeter login."
case distros.FamilyDebian, distros.FamilyUbuntu:
return "Disable it in pam-auth-update to force password-only greeter login."
default:
return "Disable it in your distro PAM manager (authselect/pam-auth-update) or in the included PAM stack to force password-only greeter login."
}
}
func isPackageOnlyGreeterDistro() bool {
osInfo, err := distros.GetOSInfo()
if err != nil {
@@ -1568,22 +1598,55 @@ func checkGreeterStatus() error {
fmt.Println(" ⚠ Legacy unmanaged DMS PAM lines detected. Run 'dms greeter sync' to normalize.")
allGood = false
}
enableFprintToggle, enableU2fToggle := false, false
if enableFprint, enableU2f, settingsErr := greeter.ReadGreeterAuthToggles(homeDir); settingsErr == nil {
enableFprintToggle = enableFprint
enableU2fToggle = enableU2f
} else {
fmt.Printf(" Could not read greeter auth toggles from settings: %v\n", settingsErr)
}
includedFprintFile := greeter.DetectIncludedPamModule(string(pamData), "pam_fprintd.so")
showIncludedFprintNotice := false
if includedFprintFile != "" {
if enableFprint, _, settingsErr := greeter.ReadGreeterAuthToggles(homeDir); settingsErr == nil && enableFprint {
showIncludedFprintNotice = greeter.FingerprintAuthAvailableForCurrentUser()
includedU2fFile := greeter.DetectIncludedPamModule(string(pamData), "pam_u2f.so")
fprintAvailableForCurrentUser := greeter.FingerprintAuthAvailableForCurrentUser()
if managedFprint && includedFprintFile != "" {
fmt.Printf(" ⚠ pam_fprintd found in both DMS managed block and %s.\n", includedFprintFile)
fmt.Println(" Double fingerprint auth detected — run 'dms greeter sync' to resolve.")
allGood = false
}
if managedU2f && includedU2fFile != "" {
fmt.Printf(" ⚠ pam_u2f found in both DMS managed block and %s.\n", includedU2fFile)
fmt.Println(" Double security-key auth detected — run 'dms greeter sync' to resolve.")
allGood = false
}
if includedFprintFile != "" && !managedFprint {
if enableFprintToggle {
fmt.Printf(" Fingerprint auth is enabled via included %s.\n", includedFprintFile)
if fprintAvailableForCurrentUser {
fmt.Println(" DMS toggle is enabled, and effective auth is coming from the included PAM stack.")
} else {
fmt.Println(" No enrolled fingerprints detected for the current user; password auth remains the effective path.")
}
} else {
if fprintAvailableForCurrentUser {
fmt.Printf(" ⚠ Fingerprint auth is active via included %s while DMS fingerprint toggle is off.\n", includedFprintFile)
fmt.Printf(" %s\n", systemPamManagerRemediationHint())
} else {
fmt.Printf(" pam_fprintd is present via included %s, but no enrolled fingerprints were detected for user %s.\n", includedFprintFile, currentUser.Username)
fmt.Println(" Password auth remains the effective login path.")
}
}
}
if managedFprint {
if includedFprintFile != "" {
fmt.Printf(" ⚠ pam_fprintd found in both DMS managed block and %s.\n", includedFprintFile)
fmt.Println(" Double fingerprint auth detected — run 'dms greeter sync' to resolve.")
allGood = false
if includedU2fFile != "" && !managedU2f {
if enableU2fToggle {
fmt.Printf(" Security-key auth is enabled via included %s.\n", includedU2fFile)
fmt.Println(" DMS toggle is enabled, but effective auth is coming from the included PAM stack.")
} else {
fmt.Printf(" ⚠ Security-key auth is active via included %s while DMS security-key toggle is off.\n", includedU2fFile)
fmt.Printf(" %s\n", systemPamManagerRemediationHint())
}
} else if includedFprintFile != "" && showIncludedFprintNotice {
fmt.Printf(" Fingerprint auth is enabled via included %s.\n", includedFprintFile)
fmt.Println(" The DMS toggle only controls the managed block; disable fingerprint in authselect/pam-auth-update for password-only greeter login.")
}
}

View File

@@ -1424,9 +1424,30 @@ func FingerprintAuthAvailableForCurrentUser() bool {
return FingerprintAuthAvailableForUser(username)
}
func pamManagerHintForCurrentDistro() string {
osInfo, err := distros.GetOSInfo()
if err != nil {
return "Disable it in your PAM manager (authselect/pam-auth-update) or in the included PAM stack to force password-only greeter login."
}
config, exists := distros.Registry[osInfo.Distribution.ID]
if !exists {
return "Disable it in your PAM manager (authselect/pam-auth-update) or in the included PAM stack to force password-only greeter login."
}
switch config.Family {
case distros.FamilyFedora:
return "Disable it in authselect to force password-only greeter login."
case distros.FamilyDebian, distros.FamilyUbuntu:
return "Disable it in pam-auth-update to force password-only greeter login."
default:
return "Disable it in your distro PAM manager (authselect/pam-auth-update) or in the included PAM stack to force password-only greeter login."
}
}
func syncGreeterPamConfig(homeDir string, logFunc func(string), sudoPassword string, forceAuth bool) error {
var wantFprint, wantU2f bool
fprintToggleEnabled := forceAuth
u2fToggleEnabled := forceAuth
if forceAuth {
wantFprint = pamModuleExists("pam_fprintd.so")
wantU2f = pamModuleExists("pam_u2f.so")
@@ -1436,6 +1457,7 @@ func syncGreeterPamConfig(homeDir string, logFunc func(string), sudoPassword str
return err
}
fprintToggleEnabled = settings.GreeterEnableFprint
u2fToggleEnabled = settings.GreeterEnableU2f
fprintModule := pamModuleExists("pam_fprintd.so")
u2fModule := pamModuleExists("pam_u2f.so")
wantFprint = settings.GreeterEnableFprint && fprintModule
@@ -1464,14 +1486,42 @@ func syncGreeterPamConfig(homeDir string, logFunc func(string), sudoPassword str
content, _ = stripLegacyGreeterPamLines(content)
includedFprintFile := DetectIncludedPamModule(content, "pam_fprintd.so")
includedU2fFile := DetectIncludedPamModule(content, "pam_u2f.so")
fprintAvailableForCurrentUser := FingerprintAuthAvailableForCurrentUser()
if wantFprint && includedFprintFile != "" {
logFunc("⚠ pam_fprintd already present in included " + includedFprintFile + " (managed by authselect/pam-auth-update). Skipping DMS fprint block to avoid double-fingerprint auth.")
wantFprint = false
}
showIncludedFprintNotice := fprintToggleEnabled && FingerprintAuthAvailableForCurrentUser()
if !wantFprint && includedFprintFile != "" && showIncludedFprintNotice {
logFunc(" Fingerprint auth is still enabled via included " + includedFprintFile + ".")
logFunc(" Disable fingerprint in your system PAM manager (authselect/pam-auth-update) to force password-only greeter login.")
if wantU2f && includedU2fFile != "" {
logFunc("⚠ pam_u2f already present in included " + includedU2fFile + " (managed by authselect/pam-auth-update). Skipping DMS U2F block to avoid double security-key auth.")
wantU2f = false
}
if !wantFprint && includedFprintFile != "" {
if fprintToggleEnabled {
logFunc(" Fingerprint auth is still enabled via included " + includedFprintFile + ".")
if fprintAvailableForCurrentUser {
logFunc(" DMS toggle is enabled, and effective auth is provided by the included PAM stack.")
} else {
logFunc(" No enrolled fingerprints detected for the current user; password auth remains the effective path.")
}
} else {
if fprintAvailableForCurrentUser {
logFunc("⚠ Fingerprint auth is active via included " + includedFprintFile + " while DMS fingerprint toggle is off.")
logFunc(" " + pamManagerHintForCurrentDistro())
} else {
logFunc(" pam_fprintd is present via included " + includedFprintFile + ", but no enrolled fingerprints were detected for the current user.")
logFunc(" Password auth remains the effective login path.")
}
}
}
if !wantU2f && includedU2fFile != "" {
if u2fToggleEnabled {
logFunc(" Security-key auth is still enabled via included " + includedU2fFile + ".")
logFunc(" DMS toggle is enabled, but effective auth is provided by the included PAM stack.")
} else {
logFunc("⚠ Security-key auth is active via included " + includedU2fFile + " while DMS security-key toggle is off.")
logFunc(" " + pamManagerHintForCurrentDistro())
}
}
if wantFprint || wantU2f {

View File

@@ -50,9 +50,13 @@ Item {
property string faillockConfigText: ""
property bool greeterWallpaperOverrideExists: false
property string externalAuthAutoStartedForUser: ""
property int passwordSessionTransitionRetryCount: 0
property int maxPasswordSessionTransitionRetries: 2
readonly property bool greeterPamHasFprint: pamModuleEnabled(greetdPamText, "pam_fprintd") || (greetdPamText.includes("system-auth") && pamModuleEnabled(systemAuthPamText, "pam_fprintd")) || (greetdPamText.includes("common-auth") && pamModuleEnabled(commonAuthPamText, "pam_fprintd")) || (greetdPamText.includes("password-auth") && pamModuleEnabled(passwordAuthPamText, "pam_fprintd"))
readonly property bool greeterPamHasU2f: pamModuleEnabled(greetdPamText, "pam_u2f") || (greetdPamText.includes("system-auth") && pamModuleEnabled(systemAuthPamText, "pam_u2f")) || (greetdPamText.includes("common-auth") && pamModuleEnabled(commonAuthPamText, "pam_u2f")) || (greetdPamText.includes("password-auth") && pamModuleEnabled(passwordAuthPamText, "pam_u2f"))
readonly property bool greeterExternalAuthAvailable: (greeterPamHasFprint && GreetdSettings.greeterEnableFprint) || (greeterPamHasU2f && GreetdSettings.greeterEnableU2f)
readonly property bool greeterExternalAuthCapable: greeterPamHasFprint || greeterPamHasU2f
readonly property bool greeterExternalAuthEnabledByToggle: (greeterPamHasFprint && GreetdSettings.greeterEnableFprint) || (greeterPamHasU2f && GreetdSettings.greeterEnableU2f)
readonly property bool greeterExternalAuthAvailable: greeterExternalAuthCapable
function initWeatherService() {
if (weatherInitialized)
@@ -208,6 +212,13 @@ Item {
authFeedbackMessage = "";
}
function resetPasswordSessionTransition(clearSubmitRequest) {
cancelingExternalAuthForPassword = false;
passwordSessionTransitionRetryCount = 0;
if (clearSubmitRequest)
passwordSubmitRequested = false;
}
Connections {
target: GreetdSettings
function onSettingsLoadedChanged() {
@@ -348,8 +359,7 @@ Item {
PortalService.getGreeterUserProfileImage(user);
GreeterState.passwordBuffer = "";
pendingPasswordResponse = false;
passwordSubmitRequested = false;
cancelingExternalAuthForPassword = false;
resetPasswordSessionTransition(true);
maybeAutoStartExternalAuth();
}
@@ -357,8 +367,7 @@ Item {
if (!GreeterState.passwordBuffer || GreeterState.passwordBuffer.length === 0)
return false;
pendingPasswordResponse = false;
passwordSubmitRequested = false;
cancelingExternalAuthForPassword = false;
resetPasswordSessionTransition(true);
awaitingExternalAuth = false;
authTimeout.interval = defaultAuthTimeoutMs;
authTimeout.restart();
@@ -369,9 +378,24 @@ Item {
}
function requestPasswordSessionTransition() {
if (!GreeterState.passwordBuffer || GreeterState.passwordBuffer.length === 0)
return;
if (cancelingExternalAuthForPassword)
return;
if (passwordSessionTransitionRetryCount >= maxPasswordSessionTransitionRetries) {
pendingPasswordResponse = false;
awaitingExternalAuth = false;
authTimeout.interval = defaultAuthTimeoutMs;
authTimeout.stop();
resetPasswordSessionTransition(true);
GreeterState.pamState = "error";
authFeedbackMessage = currentAuthMessage();
placeholderDelay.restart();
Greetd.cancelSession();
return;
}
cancelingExternalAuthForPassword = true;
passwordSessionTransitionRetryCount = passwordSessionTransitionRetryCount + 1;
awaitingExternalAuth = false;
pendingPasswordResponse = false;
authTimeout.interval = defaultAuthTimeoutMs;
@@ -390,6 +414,7 @@ Item {
submitBufferedPassword();
else if (awaitingExternalAuth && hasPasswordBuffer) {
passwordSubmitRequested = true;
requestPasswordSessionTransition();
} else if (hasPasswordBuffer)
passwordSubmitRequested = true;
return;
@@ -399,11 +424,11 @@ Item {
passwordSubmitRequested = true;
return;
}
if (!hasPasswordBuffer && !root.greeterExternalAuthAvailable)
if (!hasPasswordBuffer && !root.greeterExternalAuthEnabledByToggle)
return;
pendingPasswordResponse = false;
passwordSubmitRequested = hasPasswordBuffer;
awaitingExternalAuth = !hasPasswordBuffer && root.greeterExternalAuthAvailable;
awaitingExternalAuth = !hasPasswordBuffer && root.greeterExternalAuthEnabledByToggle;
authTimeout.interval = awaitingExternalAuth ? externalAuthTimeoutMs : defaultAuthTimeoutMs;
authTimeout.restart();
Greetd.createSession(GreeterState.username);
@@ -412,7 +437,7 @@ Item {
function maybeAutoStartExternalAuth() {
if (!GreeterState.showPasswordInput || !GreeterState.username)
return;
if (!root.greeterExternalAuthAvailable)
if (!root.greeterExternalAuthEnabledByToggle)
return;
if (GreeterState.unlocking || Greetd.state !== GreetdState.Inactive)
return;
@@ -933,7 +958,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
iconName: root.greeterPamHasFprint ? "fingerprint" : "key"
buttonSize: 32
visible: GreeterState.showPasswordInput && root.greeterExternalAuthAvailable && GreeterState.passwordBuffer.length === 0 && (Greetd.state === GreetdState.Inactive || awaitingExternalAuth || pendingPasswordResponse) && !GreeterState.unlocking
visible: GreeterState.showPasswordInput && root.greeterExternalAuthEnabledByToggle && GreeterState.passwordBuffer.length === 0 && (Greetd.state === GreetdState.Inactive || awaitingExternalAuth || pendingPasswordResponse) && !GreeterState.unlocking
enabled: visible
onClicked: root.startAuthSession()
}
@@ -1559,6 +1584,7 @@ Item {
function onAuthMessage(message, error, responseRequired, echoResponse) {
if (responseRequired) {
cancelingExternalAuthForPassword = false;
passwordSessionTransitionRetryCount = 0;
awaitingExternalAuth = false;
authTimeout.interval = defaultAuthTimeoutMs;
authTimeout.restart();
@@ -1568,6 +1594,10 @@ Item {
return;
}
pendingPasswordResponse = false;
if (passwordSubmitRequested && GreeterState.passwordBuffer && GreeterState.passwordBuffer.length > 0 && awaitingExternalAuth && !cancelingExternalAuthForPassword) {
requestPasswordSessionTransition();
return;
}
if (!passwordSubmitRequested)
awaitingExternalAuth = root.isExternalAuthPrompt(message, responseRequired);
authTimeout.interval = awaitingExternalAuth ? externalAuthTimeoutMs : defaultAuthTimeoutMs;
@@ -1587,15 +1617,14 @@ Item {
Qt.callLater(root.startAuthSession);
return;
}
passwordSubmitRequested = false;
resetPasswordSessionTransition(true);
}
}
function onReadyToLaunch() {
awaitingExternalAuth = false;
pendingPasswordResponse = false;
passwordSubmitRequested = false;
cancelingExternalAuthForPassword = false;
resetPasswordSessionTransition(true);
authTimeout.interval = defaultAuthTimeoutMs;
authTimeout.stop();
passwordFailureCount = 0;
@@ -1629,8 +1658,7 @@ Item {
function onAuthFailure(message) {
awaitingExternalAuth = false;
pendingPasswordResponse = false;
passwordSubmitRequested = false;
cancelingExternalAuthForPassword = false;
resetPasswordSessionTransition(true);
authTimeout.interval = defaultAuthTimeoutMs;
authTimeout.stop();
launchTimeout.stop();
@@ -1651,8 +1679,7 @@ Item {
function onError(error) {
awaitingExternalAuth = false;
pendingPasswordResponse = false;
passwordSubmitRequested = false;
cancelingExternalAuthForPassword = false;
resetPasswordSessionTransition(true);
authTimeout.interval = defaultAuthTimeoutMs;
authTimeout.stop();
launchTimeout.stop();
@@ -1688,8 +1715,7 @@ Item {
return;
awaitingExternalAuth = false;
pendingPasswordResponse = false;
passwordSubmitRequested = false;
cancelingExternalAuthForPassword = false;
resetPasswordSessionTransition(true);
authTimeout.interval = defaultAuthTimeoutMs;
GreeterState.pamState = "error";
authFeedbackMessage = currentAuthMessage();
@@ -1707,8 +1733,7 @@ Item {
if (!GreeterState.unlocking)
return;
pendingPasswordResponse = false;
passwordSubmitRequested = false;
cancelingExternalAuthForPassword = false;
resetPasswordSessionTransition(true);
GreeterState.unlocking = false;
GreeterState.pamState = "error";
authFeedbackMessage = currentAuthMessage();