nixos: replace 'text' with structured PAM rules (#420889)

This commit is contained in:
Paul Haerle
2026-04-14 21:22:07 +00:00
committed by GitHub
9 changed files with 931 additions and 174 deletions

View File

@@ -541,6 +541,33 @@ let
- https://github.com/qemu/qemu/blob/master/scripts/qemu-binfmt-conf.sh
*/
binfmtMagics = import ./binfmt-magics.nix;
# Utilities for working with the security.pam module (pam.nix)
pam = {
/*
Set up the ordering for a set of PAM rules using an ordered list of rules.
The input is an ordered list of PAM rules. Each rule is an attrset similar to the options
in `security.pam.services.<service>.rules.<rule>`, with two modifications:
1. The `order` option may not be given.
2. The `name` option is required.
The output is an attrset of rules suitable for `security.pam.services.<service>.rules`.
The `order` option on the resulting rules will automatically be configured according to the
(implied) ordering of the input rules.
*/
autoOrderRules = lib.flip lib.pipe [
(lib.imap1 (
index: rule:
assert lib.assertMsg (!rule ? order) "the 'order' option may not be set when using autoOrderRules";
rule // { order = lib.mkDefault (10000 + index * 100); }
))
(map (rule: lib.nameValuePair rule.name (removeAttrs rule [ "name" ])))
lib.listToAttrs
];
};
};
in
utils

View File

@@ -3,6 +3,7 @@
{
config,
lib,
utils,
pkgs,
...
}:
@@ -173,6 +174,28 @@ let
};
};
useDefaultRules = lib.mkOption {
# This option is experimental and subject to breaking changes without notice.
visible = false;
default = true;
type = lib.types.bool;
description = ''
Whether to set up the default NixOS rule stack for this service.
Set this to `false` if you want to define the entire rule stack for this service.
::: {.warning}
This option is experimental and subject to breaking changes without notice.
If you use this option in your system configuration, you will need to manually monitor this module for any changes. Otherwise, failure to adjust your configuration properly could lead to you being locked out of your system, or worse, your system could be left wide open to attackers.
If you share configuration examples that use this option, you MUST include this warning so that users are informed.
You may freely use this option within `nixpkgs`, and future changes will account for those use sites.
:::
'';
};
unixAuth = lib.mkOption {
default = true;
type = lib.types.bool;
@@ -899,16 +922,9 @@ let
# !!! TODO: move the LDAP stuff to the LDAP module, and the
# Samba stuff to the Samba module. This requires that the PAM
# module provides the right hooks.
rules =
let
autoOrderRules = lib.flip lib.pipe [
(lib.imap1 (index: rule: rule // { order = lib.mkDefault (10000 + index * 100); }))
(map (rule: lib.nameValuePair rule.name (removeAttrs rule [ "name" ])))
lib.listToAttrs
];
in
{
account = autoOrderRules [
rules = (
lib.optionalAttrs cfg.useDefaultRules {
account = utils.pam.autoOrderRules [
{
name = "ldap";
enable = use_ldap;
@@ -989,7 +1005,7 @@ let
];
auth = autoOrderRules (
auth = utils.pam.autoOrderRules (
[
{
name = "oslogin_login";
@@ -1362,7 +1378,7 @@ let
]
);
password = autoOrderRules [
password = utils.pam.autoOrderRules [
{
name = "systemd_home";
enable = config.services.homed.enable;
@@ -1447,7 +1463,7 @@ let
}
];
session = autoOrderRules [
session = utils.pam.autoOrderRules [
{
name = "env";
enable = cfg.setEnvironment;
@@ -1679,7 +1695,8 @@ let
modulePath = "${pkgs.intune-portal}/lib/security/pam_intune.so";
}
];
};
}
);
};
};
@@ -2554,16 +2571,30 @@ in
};
security.pam.services = {
other.text = ''
auth required pam_warn.so
auth required pam_deny.so
account required pam_warn.so
account required pam_deny.so
password required pam_warn.so
password required pam_deny.so
session required pam_warn.so
session required pam_deny.so
'';
other = {
useDefaultRules = false;
rules =
let
rules = utils.pam.autoOrderRules [
{
name = "warn";
control = "required";
modulePath = "${package}/lib/security/pam_warn.so";
}
{
name = "deny";
control = "required";
modulePath = "${package}/lib/security/pam_deny.so";
}
];
in
{
auth = rules;
account = rules;
password = rules;
session = rules;
};
};
# Most of these should be moved to specific modules.
i3lock.enable = lib.mkDefault config.programs.i3lock.enable;

View File

@@ -1,6 +1,7 @@
{
config,
lib,
utils,
pkgs,
...
}:
@@ -383,67 +384,280 @@ in
# GDM LFS PAM modules, adapted somehow to NixOS
security.pam.services = {
gdm-launch-environment.text = ''
auth required pam_succeed_if.so audit quiet_success user ingroup gdm
auth optional pam_permit.so
gdm-launch-environment = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "gdm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"ingroup"
"gdm"
];
}
{
name = "permit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
account required pam_succeed_if.so audit quiet_success user ingroup gdm
account sufficient pam_unix.so
account = utils.pam.autoOrderRules [
{
name = "gdm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"ingroup"
"gdm"
];
}
{
name = "unix";
control = "sufficient";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
}
];
password required pam_deny.so
password = utils.pam.autoOrderRules [
{
name = "deny";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_deny.so";
}
];
session required pam_succeed_if.so audit quiet_success user ingroup gdm
session required pam_env.so conffile=/etc/pam/environment readenv=0
session optional ${config.systemd.package}/lib/security/pam_systemd.so
session optional pam_keyinit.so force revoke
session optional pam_permit.so
'';
session = utils.pam.autoOrderRules [
{
name = "gdm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"ingroup"
"gdm"
];
}
{
name = "env";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_env.so";
settings.conffile = "/etc/pam/environment";
settings.readenv = 0;
}
{
name = "systemd";
control = "optional";
modulePath = "${config.systemd.package}/lib/security/pam_systemd.so";
}
{
name = "keyinit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_keyinit.so";
settings.force = true;
settings.revoke = true;
}
{
name = "permit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
};
};
gdm-password.text = ''
auth substack login
account include login
password substack login
session include login
'';
gdm-password = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "login";
control = "substack";
modulePath = "login";
}
];
account = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
password = utils.pam.autoOrderRules [
{
name = "login";
control = "substack";
modulePath = "login";
}
];
session = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
gdm-autologin.text = ''
auth requisite pam_nologin.so
auth required pam_succeed_if.so uid >= 1000 quiet
${lib.optionalString (pamLogin.enable && pamLogin.enableGnomeKeyring) ''
auth [success=ok default=1] ${gdm}/lib/security/pam_gdm.so
auth optional ${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so
''}
auth required pam_permit.so
gdm-autologin = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "nologin";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_nologin.so";
}
{
name = "gdm-normal-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.quiet = true;
args = lib.mkBefore [
"uid"
">="
"1000"
];
}
{
name = "gdm";
enable = pamLogin.enable && pamLogin.enableGnomeKeyring;
control = "[success=ok default=1]";
modulePath = "${gdm}/lib/security/pam_gdm.so";
}
{
name = "gnome_keyring";
enable = pamLogin.enable && pamLogin.enableGnomeKeyring;
control = "optional";
modulePath = "${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so";
}
{
name = "permit";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
account sufficient pam_unix.so
account = utils.pam.autoOrderRules [
{
name = "unix";
control = "sufficient";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
}
];
password requisite pam_unix.so nullok yescrypt
password = utils.pam.autoOrderRules [
{
name = "unix";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
settings.nullok = true;
settings.yescrypt = true;
}
];
session optional pam_keyinit.so revoke
session include login
'';
session = utils.pam.autoOrderRules [
{
name = "keyinit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_keyinit.so";
settings.revoke = true;
}
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
# This would block password prompt when included by gdm-password.
# GDM will instead run gdm-fingerprint in parallel.
login.fprintAuth = lib.mkIf config.services.fprintd.enable false;
gdm-fingerprint.text = lib.mkIf config.services.fprintd.enable ''
auth required pam_shells.so
auth requisite pam_nologin.so
auth requisite pam_faillock.so preauth
auth required ${pkgs.fprintd}/lib/security/pam_fprintd.so
auth required pam_env.so conffile=/etc/pam/environment readenv=0
${lib.optionalString (pamLogin.enable && pamLogin.enableGnomeKeyring) ''
auth [success=ok default=1] ${gdm}/lib/security/pam_gdm.so
auth optional ${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so
''}
gdm-fingerprint = lib.mkIf config.services.fprintd.enable {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "shells";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_shells.so";
}
{
name = "nologin";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_nologin.so";
}
{
name = "faillock";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_faillock.so";
settings.preauth = true;
}
{
name = "fprintd";
control = "required";
modulePath = "${pkgs.fprintd}/lib/security/pam_fprintd.so";
}
{
name = "env";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_env.so";
settings.conffile = "/etc/pam/environment";
settings.readenv = 0;
}
{
name = "gdm";
enable = pamLogin.enable && pamLogin.enableGnomeKeyring;
control = "[success=ok default=1]";
modulePath = "${gdm}/lib/security/pam_gdm.so";
}
{
name = "gnome_keyring";
enable = pamLogin.enable && pamLogin.enableGnomeKeyring;
control = "optional";
modulePath = "${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so";
}
];
account include login
account = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
password required pam_deny.so
password = utils.pam.autoOrderRules [
{
name = "deny";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_deny.so";
}
];
session include login
'';
session = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
};
};

View File

@@ -1,6 +1,7 @@
{
config,
lib,
utils,
pkgs,
...
}:
@@ -105,17 +106,58 @@ in
};
}
// optionalAttrs dmcfg.autoLogin.enable {
ly-autologin.text = ''
auth requisite pam_nologin.so
auth required pam_succeed_if.so uid >= 1000 quiet
auth required pam_permit.so
ly-autologin = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "nologin";
control = "requisite";
modulePath = "pam_nologin.so";
}
{
name = "ly-normal-user";
control = "required";
modulePath = "pam_succeed_if.so";
settings.quiet = true;
args = lib.mkBefore [
"uid"
">="
"1000"
];
}
{
name = "permit";
control = "required";
modulePath = "pam_permit.so";
}
];
account include ly
account = utils.pam.autoOrderRules [
{
name = "ly";
control = "include";
modulePath = "ly";
}
];
password include ly
password = utils.pam.autoOrderRules [
{
name = "ly";
control = "include";
modulePath = "ly";
}
];
session include ly
'';
session = utils.pam.autoOrderRules [
{
name = "ly";
control = "include";
modulePath = "ly";
}
];
};
};
};
environment = {

View File

@@ -1,6 +1,7 @@
{
config,
lib,
utils,
pkgs,
...
}:
@@ -83,39 +84,133 @@ in
environment.etc."plasmalogin.conf.d/99-user.conf".source = userConfigFile;
security.pam.services = {
plasmalogin.text = ''
auth substack login
account include login
password substack login
session include login
'';
plasmalogin = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "login";
control = "substack";
modulePath = "login";
}
];
account = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
password = utils.pam.autoOrderRules [
{
name = "login";
control = "substack";
modulePath = "login";
}
];
session = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
plasmalogin-autologin.text = ''
auth requisite pam_nologin.so
auth required pam_permit.so
plasmalogin-autologin = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "nologin";
control = "requisite";
modulePath = "pam_nologin.so";
}
{
name = "permit";
control = "required";
modulePath = "pam_permit.so";
}
];
account include plasmalogin
password include plasmalogin
session include plasmalogin
'';
account = utils.pam.autoOrderRules [
{
name = "plasmalogin";
control = "include";
modulePath = "plasmalogin";
}
];
password = utils.pam.autoOrderRules [
{
name = "plasmalogin";
control = "include";
modulePath = "plasmalogin";
}
];
session = utils.pam.autoOrderRules [
{
name = "plasmalogin";
control = "include";
modulePath = "plasmalogin";
}
];
};
};
plasmalogin-greeter.text = ''
# Load environment from /etc/environment and ~/.pam_environment
auth required pam_env.so conffile=/etc/pam/environment readenv=0
plasmalogin-greeter = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
# Load environment from /etc/environment and ~/.pam_environment
name = "env";
control = "required";
modulePath = "pam_env.so";
settings.conffile = "/etc/pam/environment";
settings.readenv = 0;
}
{
# Always let the greeter start without authentication
name = "permit";
control = "required";
modulePath = "pam_permit.so";
}
];
# Always let the greeter start without authentication
auth required pam_permit.so
account = utils.pam.autoOrderRules [
{
# No action required for account management
name = "permit";
control = "required";
modulePath = "pam_permit.so";
}
];
# No action required for account management
account required pam_permit.so
password = utils.pam.autoOrderRules [
{
# Can't change password
name = "deny";
control = "required";
modulePath = "pam_deny.so";
}
];
# Can't change password
password required pam_deny.so
# Setup session
session required pam_unix.so
session optional ${config.systemd.package}/lib/security/pam_systemd.so
'';
session = utils.pam.autoOrderRules [
{
# Setup session
name = "unix";
control = "required";
modulePath = "pam_unix.so";
}
{
name = "systemd";
control = "optional";
modulePath = "${config.systemd.package}/lib/security/pam_systemd.so";
}
];
};
};
};
# FIXME: use upstream sysusers

View File

@@ -1,6 +1,7 @@
{
config,
lib,
utils,
pkgs,
...
}:
@@ -368,40 +369,184 @@ in
};
security.pam.services = {
sddm.text = ''
auth substack login
account include login
password substack login
session include login
'';
sddm = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "login";
control = "substack";
modulePath = "login";
}
];
account = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
password = utils.pam.autoOrderRules [
{
name = "login";
control = "substack";
modulePath = "login";
}
];
session = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
sddm-greeter.text = ''
auth required pam_succeed_if.so audit quiet_success user = sddm
auth optional pam_permit.so
sddm-greeter = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "sddm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"="
"sddm"
];
}
{
name = "permit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
account required pam_succeed_if.so audit quiet_success user = sddm
account sufficient pam_unix.so
account = utils.pam.autoOrderRules [
{
name = "sddm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"="
"sddm"
];
}
{
name = "unix";
control = "sufficient";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
}
];
password required pam_deny.so
password = utils.pam.autoOrderRules [
{
name = "deny";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_deny.so";
}
];
session required pam_succeed_if.so audit quiet_success user = sddm
session required pam_env.so conffile=/etc/pam/environment readenv=0
session optional ${config.systemd.package}/lib/security/pam_systemd.so
session optional pam_keyinit.so force revoke
session optional pam_permit.so
'';
session = utils.pam.autoOrderRules [
{
name = "sddm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"="
"sddm"
];
}
{
name = "env";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_env.so";
settings.conffile = "/etc/pam/environment";
settings.readenv = 0;
}
{
name = "systemd";
control = "optional";
modulePath = "${config.systemd.package}/lib/security/pam_systemd.so";
}
{
name = "keyinit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_keyinit.so";
settings.force = true;
settings.revoke = true;
}
{
name = "permit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
};
};
sddm-autologin.text = ''
auth requisite pam_nologin.so
auth required pam_succeed_if.so uid >= ${toString cfg.autoLogin.minimumUid} quiet
auth required pam_permit.so
sddm-autologin = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "nologin";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_nologin.so";
}
{
name = "sddm-autologin-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.quiet = true;
args = lib.mkBefore [
"uid"
">="
(toString cfg.autoLogin.minimumUid)
];
}
{
name = "permit";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
account include sddm
account = utils.pam.autoOrderRules [
{
name = "sddm";
control = "include";
modulePath = "sddm";
}
];
password include sddm
password = utils.pam.autoOrderRules [
{
name = "sddm";
control = "include";
modulePath = "sddm";
}
];
session include sddm
'';
session = utils.pam.autoOrderRules [
{
name = "sddm";
control = "include";
modulePath = "sddm";
}
];
};
};
};
users.users.sddm = {

View File

@@ -1,6 +1,7 @@
{
config,
lib,
utils,
pkgs,
...
}:
@@ -333,9 +334,23 @@ in
};
};
security.pam.services.vsftpd.text = mkIf (cfg.enableVirtualUsers && cfg.userDbPath != null) ''
auth required pam_userdb.so db=${cfg.userDbPath}
account required pam_userdb.so db=${cfg.userDbPath}
'';
security.pam.services.vsftpd = mkIf (cfg.enableVirtualUsers && cfg.userDbPath != null) {
useDefaultRules = false;
rules =
let
rules = utils.pam.autoOrderRules [
{
name = "userdb";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_userdb.so";
settings.db = cfg.userDbPath;
}
];
in
{
auth = rules;
account = rules;
};
};
};
}

View File

@@ -2,6 +2,7 @@
config,
pkgs,
lib,
utils,
...
}:
@@ -105,13 +106,45 @@ in
security.polkit.enable = true;
security.pam.services.cage.text = ''
auth required pam_unix.so nullok
account required pam_unix.so
session required pam_unix.so
session required pam_env.so conffile=/etc/pam/environment readenv=0
session required ${config.systemd.package}/lib/security/pam_systemd.so
'';
security.pam.services.cage = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "unix";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
settings.nullok = true;
}
];
account = utils.pam.autoOrderRules [
{
name = "unix";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
}
];
session = utils.pam.autoOrderRules [
{
name = "unix";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
}
{
name = "env";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_env.so";
settings.conffile = "/etc/pam/environment";
settings.readenv = 0;
}
{
name = "systemd";
control = "required";
modulePath = "${config.systemd.package}/lib/security/pam_systemd.so";
}
];
};
};
hardware.graphics.enable = mkDefault true;

View File

@@ -1,6 +1,7 @@
{
config,
lib,
utils,
pkgs,
...
}:
@@ -279,47 +280,201 @@ in
security.polkit.enable = true;
security.pam.services.lightdm.text = ''
auth substack login
account include login
password substack login
session include login
''
# https://github.com/elementary/switchboard-plug-parental-controls/blob/8.0.1/src/daemon/Server.vala#L325
# Must specify conffile since pam_time defaults to ${linux-pam}/etc/security/time.conf.
+ lib.optionalString config.services.pantheon.parental-controls.enable ''
account required pam_time.so conffile=/etc/security/time.conf
'';
security.pam.services.lightdm = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "login";
control = "substack";
modulePath = "login";
}
];
account = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
{
name = "time";
# https://github.com/elementary/switchboard-plug-parental-controls/blob/8.0.1/src/daemon/Server.vala#L325
enable = config.services.pantheon.parental-controls.enable;
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_time.so";
# Must specify conffile since pam_time defaults to ${linux-pam}/etc/security/time.conf.
settings.conffile = "/etc/security/time.conf";
}
];
password = utils.pam.autoOrderRules [
{
name = "login";
control = "substack";
modulePath = "login";
}
];
session = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
security.pam.services.lightdm-greeter.text = ''
auth required pam_succeed_if.so audit quiet_success user = lightdm
auth optional pam_permit.so
security.pam.services.lightdm-greeter = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "lightdm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"="
"lightdm"
];
}
{
name = "permit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
account required pam_succeed_if.so audit quiet_success user = lightdm
account sufficient pam_unix.so
account = utils.pam.autoOrderRules [
{
name = "lightdm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"="
"lightdm"
];
}
{
name = "unix";
control = "sufficient";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
}
];
password required pam_deny.so
password = utils.pam.autoOrderRules [
{
name = "deny";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_deny.so";
}
];
session required pam_succeed_if.so audit quiet_success user = lightdm
session required pam_env.so conffile=/etc/pam/environment readenv=0
session optional ${config.systemd.package}/lib/security/pam_systemd.so
session optional pam_keyinit.so force revoke
session optional pam_permit.so
'';
session = utils.pam.autoOrderRules [
{
name = "lightdm-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.audit = true;
settings.quiet_success = true;
args = lib.mkAfter [
"user"
"="
"lightdm"
];
}
{
name = "env";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_env.so";
settings.conffile = "/etc/pam/environment";
settings.readenv = 0;
}
{
name = "systemd";
control = "optional";
modulePath = "${config.systemd.package}/lib/security/pam_systemd.so";
}
{
name = "keyinit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_keyinit.so";
settings.force = true;
settings.revoke = true;
}
{
name = "permit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
};
};
security.pam.services.lightdm-autologin.text = ''
auth requisite pam_nologin.so
security.pam.services.lightdm-autologin = {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "nologin";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_nologin.so";
}
{
name = "lightdm-normal-user";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_succeed_if.so";
settings.quiet = true;
args = lib.mkBefore [
"uid"
">="
"1000"
];
}
{
name = "permit";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_permit.so";
}
];
auth required pam_succeed_if.so uid >= 1000 quiet
auth required pam_permit.so
account = utils.pam.autoOrderRules [
{
name = "unix";
control = "sufficient";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
}
];
account sufficient pam_unix.so
password = utils.pam.autoOrderRules [
{
name = "unix";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_unix.so";
settings.nullok = true;
settings.yescrypt = true;
}
];
password requisite pam_unix.so nullok yescrypt
session optional pam_keyinit.so revoke
session include login
'';
session = utils.pam.autoOrderRules [
{
name = "keyinit";
control = "optional";
modulePath = "${config.security.pam.package}/lib/security/pam_keyinit.so";
settings.revoke = true;
}
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
users.users.lightdm = {
home = "/var/lib/lightdm";