Currently account pam_systemd_home.so returns PAM_SUCCESS on PAM_USER_UNKNOWN. Programs like login depend on the value returned by pam_acct_mgmt() to block a user with an expired password from login.
This is hard to get right with the current behaviour, since any error values from account pam_unix.so with a ignore action (like in the sufficient example from the manpage) results in account pam_systemd_home.so just sending a PAM_SUCCESS. Also, this forces the order of the modules to be in a certain way.
This is an alternative I found -
account [success=ok new_authtok_reqd=ok ignore=1 user_unknown=1 default=bad] pam_unix.so
account [default=1] pam_permit.so
# if reached here due to user_unknown, this will return success.
# but an actual unknown user is the fault of the application.
# account expects the user to be already authenticated and it is impossible
# that an user is already authenticated but is unknown to both account
# modules.
account required pam_systemd_home.so
account required pam_time.so
It might still be better to just return PAM_USER_UNKNOWN, so the sysadmin can test against that value in the pam configuration if they want to. Doing this change will also allow the modules to be placed in any order.
I opened #15116 and associated PR #15118 quite a while ago, where I first changed to reporting PAM_USER_UNKNOWN as is, and then force pushed to reporting PAM_IGNORE instead. I closed those because, on further reading, I thought that the current design was good enough, I never considered expiring passwords and stuff, and I knew less about PAM and tried to apply my PAM_IGNORE solution uniformly to every function. The branch was deleted long ago, so starting fresh with this.
Also: Some downstream discussion, loqs was the one who wanted the return value to be truthful and posted a patch there too.