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
+27
View File
@@ -541,6 +541,33 @@ let
- https://github.com/qemu/qemu/blob/master/scripts/qemu-binfmt-conf.sh - https://github.com/qemu/qemu/blob/master/scripts/qemu-binfmt-conf.sh
*/ */
binfmtMagics = import ./binfmt-magics.nix; 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 in
utils utils
+55 -24
View File
@@ -3,6 +3,7 @@
{ {
config, config,
lib, lib,
utils,
pkgs, 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 { unixAuth = lib.mkOption {
default = true; default = true;
type = lib.types.bool; type = lib.types.bool;
@@ -899,16 +922,9 @@ let
# !!! TODO: move the LDAP stuff to the LDAP module, and the # !!! TODO: move the LDAP stuff to the LDAP module, and the
# Samba stuff to the Samba module. This requires that the PAM # Samba stuff to the Samba module. This requires that the PAM
# module provides the right hooks. # module provides the right hooks.
rules = rules = (
let lib.optionalAttrs cfg.useDefaultRules {
autoOrderRules = lib.flip lib.pipe [ account = utils.pam.autoOrderRules [
(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 [
{ {
name = "ldap"; name = "ldap";
enable = use_ldap; enable = use_ldap;
@@ -989,7 +1005,7 @@ let
]; ];
auth = autoOrderRules ( auth = utils.pam.autoOrderRules (
[ [
{ {
name = "oslogin_login"; name = "oslogin_login";
@@ -1362,7 +1378,7 @@ let
] ]
); );
password = autoOrderRules [ password = utils.pam.autoOrderRules [
{ {
name = "systemd_home"; name = "systemd_home";
enable = config.services.homed.enable; enable = config.services.homed.enable;
@@ -1447,7 +1463,7 @@ let
} }
]; ];
session = autoOrderRules [ session = utils.pam.autoOrderRules [
{ {
name = "env"; name = "env";
enable = cfg.setEnvironment; enable = cfg.setEnvironment;
@@ -1679,7 +1695,8 @@ let
modulePath = "${pkgs.intune-portal}/lib/security/pam_intune.so"; modulePath = "${pkgs.intune-portal}/lib/security/pam_intune.so";
} }
]; ];
}; }
);
}; };
}; };
@@ -2554,16 +2571,30 @@ in
}; };
security.pam.services = { security.pam.services = {
other.text = '' other = {
auth required pam_warn.so useDefaultRules = false;
auth required pam_deny.so rules =
account required pam_warn.so let
account required pam_deny.so rules = utils.pam.autoOrderRules [
password required pam_warn.so {
password required pam_deny.so name = "warn";
session required pam_warn.so control = "required";
session required pam_deny.so 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. # Most of these should be moved to specific modules.
i3lock.enable = lib.mkDefault config.programs.i3lock.enable; i3lock.enable = lib.mkDefault config.programs.i3lock.enable;
+259 -45
View File
@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
utils,
pkgs, pkgs,
... ...
}: }:
@@ -383,67 +384,280 @@ in
# GDM LFS PAM modules, adapted somehow to NixOS # GDM LFS PAM modules, adapted somehow to NixOS
security.pam.services = { security.pam.services = {
gdm-launch-environment.text = '' gdm-launch-environment = {
auth required pam_succeed_if.so audit quiet_success user ingroup gdm useDefaultRules = false;
auth optional pam_permit.so 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 = utils.pam.autoOrderRules [
account sufficient pam_unix.so {
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 = utils.pam.autoOrderRules [
session required pam_env.so conffile=/etc/pam/environment readenv=0 {
session optional ${config.systemd.package}/lib/security/pam_systemd.so name = "gdm-user";
session optional pam_keyinit.so force revoke control = "required";
session optional pam_permit.so 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 = '' gdm-password = {
auth substack login useDefaultRules = false;
account include login rules = {
password substack login auth = utils.pam.autoOrderRules [
session include login {
''; 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 = '' gdm-autologin = {
auth requisite pam_nologin.so useDefaultRules = false;
auth required pam_succeed_if.so uid >= 1000 quiet rules = {
${lib.optionalString (pamLogin.enable && pamLogin.enableGnomeKeyring) '' auth = utils.pam.autoOrderRules [
auth [success=ok default=1] ${gdm}/lib/security/pam_gdm.so {
auth optional ${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so name = "nologin";
''} control = "requisite";
auth required pam_permit.so 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 = utils.pam.autoOrderRules [
session include login {
''; 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. # This would block password prompt when included by gdm-password.
# GDM will instead run gdm-fingerprint in parallel. # GDM will instead run gdm-fingerprint in parallel.
login.fprintAuth = lib.mkIf config.services.fprintd.enable false; login.fprintAuth = lib.mkIf config.services.fprintd.enable false;
gdm-fingerprint.text = lib.mkIf config.services.fprintd.enable '' gdm-fingerprint = lib.mkIf config.services.fprintd.enable {
auth required pam_shells.so useDefaultRules = false;
auth requisite pam_nologin.so rules = {
auth requisite pam_faillock.so preauth auth = utils.pam.autoOrderRules [
auth required ${pkgs.fprintd}/lib/security/pam_fprintd.so {
auth required pam_env.so conffile=/etc/pam/environment readenv=0 name = "shells";
${lib.optionalString (pamLogin.enable && pamLogin.enableGnomeKeyring) '' control = "required";
auth [success=ok default=1] ${gdm}/lib/security/pam_gdm.so modulePath = "${config.security.pam.package}/lib/security/pam_shells.so";
auth optional ${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.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";
}
];
};
};
}; };
}; };
+50 -8
View File
@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
utils,
pkgs, pkgs,
... ...
}: }:
@@ -105,17 +106,58 @@ in
}; };
} }
// optionalAttrs dmcfg.autoLogin.enable { // optionalAttrs dmcfg.autoLogin.enable {
ly-autologin.text = '' ly-autologin = {
auth requisite pam_nologin.so useDefaultRules = false;
auth required pam_succeed_if.so uid >= 1000 quiet rules = {
auth required pam_permit.so 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 = { environment = {
@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
utils,
pkgs, pkgs,
... ...
}: }:
@@ -83,39 +84,133 @@ in
environment.etc."plasmalogin.conf.d/99-user.conf".source = userConfigFile; environment.etc."plasmalogin.conf.d/99-user.conf".source = userConfigFile;
security.pam.services = { security.pam.services = {
plasmalogin.text = '' plasmalogin = {
auth substack login useDefaultRules = false;
account include login rules = {
password substack login auth = utils.pam.autoOrderRules [
session include login {
''; 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 = '' plasmalogin-autologin = {
auth requisite pam_nologin.so useDefaultRules = false;
auth required pam_permit.so rules = {
auth = utils.pam.autoOrderRules [
{
name = "nologin";
control = "requisite";
modulePath = "pam_nologin.so";
}
{
name = "permit";
control = "required";
modulePath = "pam_permit.so";
}
];
account include plasmalogin account = utils.pam.autoOrderRules [
password include plasmalogin {
session include plasmalogin 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 = '' plasmalogin-greeter = {
# Load environment from /etc/environment and ~/.pam_environment useDefaultRules = false;
auth required pam_env.so conffile=/etc/pam/environment readenv=0 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 account = utils.pam.autoOrderRules [
auth required pam_permit.so {
# No action required for account management
name = "permit";
control = "required";
modulePath = "pam_permit.so";
}
];
# No action required for account management password = utils.pam.autoOrderRules [
account required pam_permit.so {
# Can't change password
name = "deny";
control = "required";
modulePath = "pam_deny.so";
}
];
# Can't change password session = utils.pam.autoOrderRules [
password required pam_deny.so {
# Setup session
# Setup session name = "unix";
session required pam_unix.so control = "required";
session optional ${config.systemd.package}/lib/security/pam_systemd.so modulePath = "pam_unix.so";
''; }
{
name = "systemd";
control = "optional";
modulePath = "${config.systemd.package}/lib/security/pam_systemd.so";
}
];
};
};
}; };
# FIXME: use upstream sysusers # FIXME: use upstream sysusers
+171 -26
View File
@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
utils,
pkgs, pkgs,
... ...
}: }:
@@ -368,40 +369,184 @@ in
}; };
security.pam.services = { security.pam.services = {
sddm.text = '' sddm = {
auth substack login useDefaultRules = false;
account include login rules = {
password substack login auth = utils.pam.autoOrderRules [
session include login {
''; 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 = '' sddm-greeter = {
auth required pam_succeed_if.so audit quiet_success user = sddm useDefaultRules = false;
auth optional pam_permit.so 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 = utils.pam.autoOrderRules [
account sufficient pam_unix.so {
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 = utils.pam.autoOrderRules [
session required pam_env.so conffile=/etc/pam/environment readenv=0 {
session optional ${config.systemd.package}/lib/security/pam_systemd.so name = "sddm-user";
session optional pam_keyinit.so force revoke control = "required";
session optional pam_permit.so 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 = '' sddm-autologin = {
auth requisite pam_nologin.so useDefaultRules = false;
auth required pam_succeed_if.so uid >= ${toString cfg.autoLogin.minimumUid} quiet rules = {
auth required pam_permit.so 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 = { users.users.sddm = {
+19 -4
View File
@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
utils,
pkgs, pkgs,
... ...
}: }:
@@ -333,9 +334,23 @@ in
}; };
}; };
security.pam.services.vsftpd.text = mkIf (cfg.enableVirtualUsers && cfg.userDbPath != null) '' security.pam.services.vsftpd = mkIf (cfg.enableVirtualUsers && cfg.userDbPath != null) {
auth required pam_userdb.so db=${cfg.userDbPath} useDefaultRules = false;
account required pam_userdb.so db=${cfg.userDbPath} 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;
};
};
}; };
} }
+40 -7
View File
@@ -2,6 +2,7 @@
config, config,
pkgs, pkgs,
lib, lib,
utils,
... ...
}: }:
@@ -105,13 +106,45 @@ in
security.polkit.enable = true; security.polkit.enable = true;
security.pam.services.cage.text = '' security.pam.services.cage = {
auth required pam_unix.so nullok useDefaultRules = false;
account required pam_unix.so rules = {
session required pam_unix.so auth = utils.pam.autoOrderRules [
session required pam_env.so conffile=/etc/pam/environment readenv=0 {
session required ${config.systemd.package}/lib/security/pam_systemd.so 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; hardware.graphics.enable = mkDefault true;
@@ -1,6 +1,7 @@
{ {
config, config,
lib, lib,
utils,
pkgs, pkgs,
... ...
}: }:
@@ -279,47 +280,201 @@ in
security.polkit.enable = true; security.polkit.enable = true;
security.pam.services.lightdm.text = '' security.pam.services.lightdm = {
auth substack login useDefaultRules = false;
account include login rules = {
password substack login auth = utils.pam.autoOrderRules [
session include login {
'' name = "login";
# https://github.com/elementary/switchboard-plug-parental-controls/blob/8.0.1/src/daemon/Server.vala#L325 control = "substack";
# Must specify conffile since pam_time defaults to ${linux-pam}/etc/security/time.conf. modulePath = "login";
+ lib.optionalString config.services.pantheon.parental-controls.enable '' }
account required pam_time.so conffile=/etc/security/time.conf ];
''; 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 = '' security.pam.services.lightdm-greeter = {
auth required pam_succeed_if.so audit quiet_success user = lightdm useDefaultRules = false;
auth optional pam_permit.so 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 = utils.pam.autoOrderRules [
account sufficient pam_unix.so {
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 = utils.pam.autoOrderRules [
session required pam_env.so conffile=/etc/pam/environment readenv=0 {
session optional ${config.systemd.package}/lib/security/pam_systemd.so name = "lightdm-user";
session optional pam_keyinit.so force revoke control = "required";
session optional pam_permit.so 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 = '' security.pam.services.lightdm-autologin = {
auth requisite pam_nologin.so 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 account = utils.pam.autoOrderRules [
auth required pam_permit.so {
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 = utils.pam.autoOrderRules [
{
session optional pam_keyinit.so revoke name = "keyinit";
session include login control = "optional";
''; modulePath = "${config.security.pam.package}/lib/security/pam_keyinit.so";
settings.revoke = true;
}
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
users.users.lightdm = { users.users.lightdm = {
home = "/var/lib/lightdm"; home = "/var/lib/lightdm";