at 23.11-pre 55 kB view raw
1# This module provides configuration for the PAM (Pluggable 2# Authentication Modules) system. 3 4{ config, lib, pkgs, ... }: 5 6with lib; 7 8let 9 parentConfig = config; 10 11 pamOpts = { config, name, ... }: let cfg = config; in let config = parentConfig; in { 12 13 options = { 14 15 name = mkOption { 16 example = "sshd"; 17 type = types.str; 18 description = lib.mdDoc "Name of the PAM service."; 19 }; 20 21 unixAuth = mkOption { 22 default = true; 23 type = types.bool; 24 description = lib.mdDoc '' 25 Whether users can log in with passwords defined in 26 {file}`/etc/shadow`. 27 ''; 28 }; 29 30 rootOK = mkOption { 31 default = false; 32 type = types.bool; 33 description = lib.mdDoc '' 34 If set, root doesn't need to authenticate (e.g. for the 35 {command}`useradd` service). 36 ''; 37 }; 38 39 p11Auth = mkOption { 40 default = config.security.pam.p11.enable; 41 defaultText = literalExpression "config.security.pam.p11.enable"; 42 type = types.bool; 43 description = lib.mdDoc '' 44 If set, keys listed in 45 {file}`~/.ssh/authorized_keys` and 46 {file}`~/.eid/authorized_certificates` 47 can be used to log in with the associated PKCS#11 tokens. 48 ''; 49 }; 50 51 u2fAuth = mkOption { 52 default = config.security.pam.u2f.enable; 53 defaultText = literalExpression "config.security.pam.u2f.enable"; 54 type = types.bool; 55 description = lib.mdDoc '' 56 If set, users listed in 57 {file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or 58 {file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is 59 not set) are able to log in with the associated U2F key. Path can be 60 changed using {option}`security.pam.u2f.authFile` option. 61 ''; 62 }; 63 64 usshAuth = mkOption { 65 default = false; 66 type = types.bool; 67 description = lib.mdDoc '' 68 If set, users with an SSH certificate containing an authorized principal 69 in their SSH agent are able to log in. Specific options are controlled 70 using the {option}`security.pam.ussh` options. 71 72 Note that the {option}`security.pam.ussh.enable` must also be 73 set for this option to take effect. 74 ''; 75 }; 76 77 yubicoAuth = mkOption { 78 default = config.security.pam.yubico.enable; 79 defaultText = literalExpression "config.security.pam.yubico.enable"; 80 type = types.bool; 81 description = lib.mdDoc '' 82 If set, users listed in 83 {file}`~/.yubico/authorized_yubikeys` 84 are able to log in with the associated Yubikey tokens. 85 ''; 86 }; 87 88 googleAuthenticator = { 89 enable = mkOption { 90 default = false; 91 type = types.bool; 92 description = lib.mdDoc '' 93 If set, users with enabled Google Authenticator (created 94 {file}`~/.google_authenticator`) will be required 95 to provide Google Authenticator token to log in. 96 ''; 97 }; 98 }; 99 100 usbAuth = mkOption { 101 default = config.security.pam.usb.enable; 102 defaultText = literalExpression "config.security.pam.usb.enable"; 103 type = types.bool; 104 description = lib.mdDoc '' 105 If set, users listed in 106 {file}`/etc/pamusb.conf` are able to log in 107 with the associated USB key. 108 ''; 109 }; 110 111 otpwAuth = mkOption { 112 default = config.security.pam.enableOTPW; 113 defaultText = literalExpression "config.security.pam.enableOTPW"; 114 type = types.bool; 115 description = lib.mdDoc '' 116 If set, the OTPW system will be used (if 117 {file}`~/.otpw` exists). 118 ''; 119 }; 120 121 googleOsLoginAccountVerification = mkOption { 122 default = false; 123 type = types.bool; 124 description = lib.mdDoc '' 125 If set, will use the Google OS Login PAM modules 126 (`pam_oslogin_login`, 127 `pam_oslogin_admin`) to verify possible OS Login 128 users and set sudoers configuration accordingly. 129 This only makes sense to enable for the `sshd` PAM 130 service. 131 ''; 132 }; 133 134 googleOsLoginAuthentication = mkOption { 135 default = false; 136 type = types.bool; 137 description = lib.mdDoc '' 138 If set, will use the `pam_oslogin_login`'s user 139 authentication methods to authenticate users using 2FA. 140 This only makes sense to enable for the `sshd` PAM 141 service. 142 ''; 143 }; 144 145 mysqlAuth = mkOption { 146 default = config.users.mysql.enable; 147 defaultText = literalExpression "config.users.mysql.enable"; 148 type = types.bool; 149 description = lib.mdDoc '' 150 If set, the `pam_mysql` module will be used to 151 authenticate users against a MySQL/MariaDB database. 152 ''; 153 }; 154 155 fprintAuth = mkOption { 156 default = config.services.fprintd.enable; 157 defaultText = literalExpression "config.services.fprintd.enable"; 158 type = types.bool; 159 description = lib.mdDoc '' 160 If set, fingerprint reader will be used (if exists and 161 your fingerprints are enrolled). 162 ''; 163 }; 164 165 oathAuth = mkOption { 166 default = config.security.pam.oath.enable; 167 defaultText = literalExpression "config.security.pam.oath.enable"; 168 type = types.bool; 169 description = lib.mdDoc '' 170 If set, the OATH Toolkit will be used. 171 ''; 172 }; 173 174 sshAgentAuth = mkOption { 175 default = false; 176 type = types.bool; 177 description = lib.mdDoc '' 178 If set, the calling user's SSH agent is used to authenticate 179 against the keys in the calling user's 180 {file}`~/.ssh/authorized_keys`. This is useful 181 for {command}`sudo` on password-less remote systems. 182 ''; 183 }; 184 185 duoSecurity = { 186 enable = mkOption { 187 default = false; 188 type = types.bool; 189 description = lib.mdDoc '' 190 If set, use the Duo Security pam module 191 `pam_duo` for authentication. Requires 192 configuration of {option}`security.duosec` options. 193 ''; 194 }; 195 }; 196 197 startSession = mkOption { 198 default = false; 199 type = types.bool; 200 description = lib.mdDoc '' 201 If set, the service will register a new session with 202 systemd's login manager. For local sessions, this will give 203 the user access to audio devices, CD-ROM drives. In the 204 default PolicyKit configuration, it also allows the user to 205 reboot the system. 206 ''; 207 }; 208 209 setEnvironment = mkOption { 210 type = types.bool; 211 default = true; 212 description = lib.mdDoc '' 213 Whether the service should set the environment variables 214 listed in {option}`environment.sessionVariables` 215 using `pam_env.so`. 216 ''; 217 }; 218 219 setLoginUid = mkOption { 220 type = types.bool; 221 description = lib.mdDoc '' 222 Set the login uid of the process 223 ({file}`/proc/self/loginuid`) for auditing 224 purposes. The login uid is only set by entry points like 225 {command}`login` and {command}`sshd`, not by 226 commands like {command}`sudo`. 227 ''; 228 }; 229 230 ttyAudit = { 231 enable = mkOption { 232 type = types.bool; 233 default = false; 234 description = lib.mdDoc '' 235 Enable or disable TTY auditing for specified users 236 ''; 237 }; 238 239 enablePattern = mkOption { 240 type = types.nullOr types.str; 241 default = null; 242 description = lib.mdDoc '' 243 For each user matching one of comma-separated 244 glob patterns, enable TTY auditing 245 ''; 246 }; 247 248 disablePattern = mkOption { 249 type = types.nullOr types.str; 250 default = null; 251 description = lib.mdDoc '' 252 For each user matching one of comma-separated 253 glob patterns, disable TTY auditing 254 ''; 255 }; 256 257 openOnly = mkOption { 258 type = types.bool; 259 default = false; 260 description = lib.mdDoc '' 261 Set the TTY audit flag when opening the session, 262 but do not restore it when closing the session. 263 Using this option is necessary for some services 264 that don't fork() to run the authenticated session, 265 such as sudo. 266 ''; 267 }; 268 }; 269 270 forwardXAuth = mkOption { 271 default = false; 272 type = types.bool; 273 description = lib.mdDoc '' 274 Whether X authentication keys should be passed from the 275 calling user to the target user (e.g. for 276 {command}`su`) 277 ''; 278 }; 279 280 pamMount = mkOption { 281 default = config.security.pam.mount.enable; 282 defaultText = literalExpression "config.security.pam.mount.enable"; 283 type = types.bool; 284 description = lib.mdDoc '' 285 Enable PAM mount (pam_mount) system to mount filesystems on user login. 286 ''; 287 }; 288 289 allowNullPassword = mkOption { 290 default = false; 291 type = types.bool; 292 description = lib.mdDoc '' 293 Whether to allow logging into accounts that have no password 294 set (i.e., have an empty password field in 295 {file}`/etc/passwd` or 296 {file}`/etc/group`). This does not enable 297 logging into disabled accounts (i.e., that have the password 298 field set to `!`). Note that regardless of 299 what the pam_unix documentation says, accounts with hashed 300 empty passwords are always allowed to log in. 301 ''; 302 }; 303 304 nodelay = mkOption { 305 default = false; 306 type = types.bool; 307 description = lib.mdDoc '' 308 Whether the delay after typing a wrong password should be disabled. 309 ''; 310 }; 311 312 requireWheel = mkOption { 313 default = false; 314 type = types.bool; 315 description = lib.mdDoc '' 316 Whether to permit root access only to members of group wheel. 317 ''; 318 }; 319 320 limits = mkOption { 321 default = []; 322 type = limitsType; 323 description = lib.mdDoc '' 324 Attribute set describing resource limits. Defaults to the 325 value of {option}`security.pam.loginLimits`. 326 The meaning of the values is explained in {manpage}`limits.conf(5)`. 327 ''; 328 }; 329 330 showMotd = mkOption { 331 default = false; 332 type = types.bool; 333 description = lib.mdDoc "Whether to show the message of the day."; 334 }; 335 336 makeHomeDir = mkOption { 337 default = false; 338 type = types.bool; 339 description = lib.mdDoc '' 340 Whether to try to create home directories for users 341 with `$HOME`s pointing to nonexistent 342 locations on session login. 343 ''; 344 }; 345 346 updateWtmp = mkOption { 347 default = false; 348 type = types.bool; 349 description = lib.mdDoc "Whether to update {file}`/var/log/wtmp`."; 350 }; 351 352 logFailures = mkOption { 353 default = false; 354 type = types.bool; 355 description = lib.mdDoc "Whether to log authentication failures in {file}`/var/log/faillog`."; 356 }; 357 358 enableAppArmor = mkOption { 359 default = false; 360 type = types.bool; 361 description = lib.mdDoc '' 362 Enable support for attaching AppArmor profiles at the 363 user/group level, e.g., as part of a role based access 364 control scheme. 365 ''; 366 }; 367 368 enableKwallet = mkOption { 369 default = false; 370 type = types.bool; 371 description = lib.mdDoc '' 372 If enabled, pam_wallet will attempt to automatically unlock the 373 user's default KDE wallet upon login. If the user has no wallet named 374 "kdewallet", or the login password does not match their wallet 375 password, KDE will prompt separately after login. 376 ''; 377 }; 378 sssdStrictAccess = mkOption { 379 default = false; 380 type = types.bool; 381 description = lib.mdDoc "enforce sssd access control"; 382 }; 383 384 enableGnomeKeyring = mkOption { 385 default = false; 386 type = types.bool; 387 description = lib.mdDoc '' 388 If enabled, pam_gnome_keyring will attempt to automatically unlock the 389 user's default Gnome keyring upon login. If the user login password does 390 not match their keyring password, Gnome Keyring will prompt separately 391 after login. 392 ''; 393 }; 394 395 failDelay = { 396 enable = mkOption { 397 type = types.bool; 398 default = false; 399 description = lib.mdDoc '' 400 If enabled, this will replace the `FAIL_DELAY` setting from `login.defs`. 401 Change the delay on failure per-application. 402 ''; 403 }; 404 405 delay = mkOption { 406 default = 3000000; 407 type = types.int; 408 example = 1000000; 409 description = lib.mdDoc "The delay time (in microseconds) on failure."; 410 }; 411 }; 412 413 gnupg = { 414 enable = mkOption { 415 type = types.bool; 416 default = false; 417 description = lib.mdDoc '' 418 If enabled, pam_gnupg will attempt to automatically unlock the 419 user's GPG keys with the login password via 420 {command}`gpg-agent`. The keygrips of all keys to be 421 unlocked should be written to {file}`~/.pam-gnupg`, 422 and can be queried with {command}`gpg -K --with-keygrip`. 423 Presetting passphrases must be enabled by adding 424 `allow-preset-passphrase` in 425 {file}`~/.gnupg/gpg-agent.conf`. 426 ''; 427 }; 428 429 noAutostart = mkOption { 430 type = types.bool; 431 default = false; 432 description = lib.mdDoc '' 433 Don't start {command}`gpg-agent` if it is not running. 434 Useful in conjunction with starting {command}`gpg-agent` as 435 a systemd user service. 436 ''; 437 }; 438 439 storeOnly = mkOption { 440 type = types.bool; 441 default = false; 442 description = lib.mdDoc '' 443 Don't send the password immediately after login, but store for PAM 444 `session`. 445 ''; 446 }; 447 }; 448 449 zfs = mkOption { 450 default = config.security.pam.zfs.enable; 451 defaultText = literalExpression "config.security.pam.zfs.enable"; 452 type = types.bool; 453 description = lib.mdDoc '' 454 Enable unlocking and mounting of encrypted ZFS home dataset at login. 455 ''; 456 }; 457 458 text = mkOption { 459 type = types.nullOr types.lines; 460 description = lib.mdDoc "Contents of the PAM service file."; 461 }; 462 463 }; 464 465 # The resulting /etc/pam.d/* file contents are verified in 466 # nixos/tests/pam/pam-file-contents.nix. Please update tests there when 467 # changing the derivation. 468 config = { 469 name = mkDefault name; 470 setLoginUid = mkDefault cfg.startSession; 471 limits = mkDefault config.security.pam.loginLimits; 472 473 # !!! TODO: move the LDAP stuff to the LDAP module, and the 474 # Samba stuff to the Samba module. This requires that the PAM 475 # module provides the right hooks. 476 text = mkDefault 477 ( 478 '' 479 # Account management. 480 '' + 481 optionalString use_ldap '' 482 account sufficient ${pam_ldap}/lib/security/pam_ldap.so 483 '' + 484 optionalString cfg.mysqlAuth '' 485 account sufficient ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf 486 '' + 487 optionalString (config.services.sssd.enable && cfg.sssdStrictAccess==false) '' 488 account sufficient ${pkgs.sssd}/lib/security/pam_sss.so 489 '' + 490 optionalString (config.services.sssd.enable && cfg.sssdStrictAccess) '' 491 account [default=bad success=ok user_unknown=ignore] ${pkgs.sssd}/lib/security/pam_sss.so 492 '' + 493 optionalString config.security.pam.krb5.enable '' 494 account sufficient ${pam_krb5}/lib/security/pam_krb5.so 495 '' + 496 optionalString cfg.googleOsLoginAccountVerification '' 497 account [success=ok ignore=ignore default=die] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so 498 account [success=ok default=ignore] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so 499 '' + 500 optionalString config.services.homed.enable '' 501 account sufficient ${config.systemd.package}/lib/security/pam_systemd_home.so 502 '' + 503 # The required pam_unix.so module has to come after all the sufficient modules 504 # because otherwise, the account lookup will fail if the user does not exist 505 # locally, for example with MySQL- or LDAP-auth. 506 '' 507 account required pam_unix.so 508 509 # Authentication management. 510 '' + 511 optionalString cfg.googleOsLoginAuthentication '' 512 auth [success=done perm_denied=die default=ignore] ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so 513 '' + 514 optionalString cfg.rootOK '' 515 auth sufficient pam_rootok.so 516 '' + 517 optionalString cfg.requireWheel '' 518 auth required pam_wheel.so use_uid 519 '' + 520 optionalString cfg.logFailures '' 521 auth required pam_faillock.so 522 '' + 523 optionalString cfg.mysqlAuth '' 524 auth sufficient ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf 525 '' + 526 optionalString (config.security.pam.enableSSHAgentAuth && cfg.sshAgentAuth) '' 527 auth sufficient ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so file=${lib.concatStringsSep ":" config.services.openssh.authorizedKeysFiles} 528 '' + 529 (let p11 = config.security.pam.p11; in optionalString cfg.p11Auth '' 530 auth ${p11.control} ${pkgs.pam_p11}/lib/security/pam_p11.so ${pkgs.opensc}/lib/opensc-pkcs11.so 531 '') + 532 (let u2f = config.security.pam.u2f; in optionalString cfg.u2fAuth ('' 533 auth ${u2f.control} ${pkgs.pam_u2f}/lib/security/pam_u2f.so ${optionalString u2f.debug "debug"} ${optionalString (u2f.authFile != null) "authfile=${u2f.authFile}"} '' 534 + ''${optionalString u2f.interactive "interactive"} ${optionalString u2f.cue "cue"} ${optionalString (u2f.appId != null) "appid=${u2f.appId}"} ${optionalString (u2f.origin != null) "origin=${u2f.origin}"} 535 '')) + 536 optionalString cfg.usbAuth '' 537 auth sufficient ${pkgs.pam_usb}/lib/security/pam_usb.so 538 '' + 539 (let ussh = config.security.pam.ussh; in optionalString (config.security.pam.ussh.enable && cfg.usshAuth) '' 540 auth ${ussh.control} ${pkgs.pam_ussh}/lib/security/pam_ussh.so ${optionalString (ussh.caFile != null) "ca_file=${ussh.caFile}"} ${optionalString (ussh.authorizedPrincipals != null) "authorized_principals=${ussh.authorizedPrincipals}"} ${optionalString (ussh.authorizedPrincipalsFile != null) "authorized_principals_file=${ussh.authorizedPrincipalsFile}"} ${optionalString (ussh.group != null) "group=${ussh.group}"} 541 '') + 542 (let oath = config.security.pam.oath; in optionalString cfg.oathAuth '' 543 auth requisite ${pkgs.oath-toolkit}/lib/security/pam_oath.so window=${toString oath.window} usersfile=${toString oath.usersFile} digits=${toString oath.digits} 544 '') + 545 (let yubi = config.security.pam.yubico; in optionalString cfg.yubicoAuth '' 546 auth ${yubi.control} ${pkgs.yubico-pam}/lib/security/pam_yubico.so mode=${toString yubi.mode} ${optionalString (yubi.challengeResponsePath != null) "chalresp_path=${yubi.challengeResponsePath}"} ${optionalString (yubi.mode == "client") "id=${toString yubi.id}"} ${optionalString yubi.debug "debug"} 547 '') + 548 optionalString cfg.fprintAuth '' 549 auth sufficient ${pkgs.fprintd}/lib/security/pam_fprintd.so 550 '' + 551 # Modules in this block require having the password set in PAM_AUTHTOK. 552 # pam_unix is marked as 'sufficient' on NixOS which means nothing will run 553 # after it succeeds. Certain modules need to run after pam_unix 554 # prompts the user for password so we run it once with 'optional' at an 555 # earlier point and it will run again with 'sufficient' further down. 556 # We use try_first_pass the second time to avoid prompting password twice. 557 # 558 # The same principle applies to systemd-homed 559 (optionalString ((cfg.unixAuth || config.services.homed.enable) && 560 (config.security.pam.enableEcryptfs 561 || config.security.pam.enableFscrypt 562 || cfg.pamMount 563 || cfg.enableKwallet 564 || cfg.enableGnomeKeyring 565 || cfg.googleAuthenticator.enable 566 || cfg.gnupg.enable 567 || cfg.failDelay.enable 568 || cfg.duoSecurity.enable 569 || cfg.zfs)) 570 ( 571 optionalString config.services.homed.enable '' 572 auth optional ${config.systemd.package}/lib/security/pam_systemd_home.so 573 '' + 574 optionalString cfg.unixAuth '' 575 auth optional pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth 576 '' + 577 optionalString config.security.pam.enableEcryptfs '' 578 auth optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so unwrap 579 '' + 580 optionalString config.security.pam.enableFscrypt '' 581 auth optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so 582 '' + 583 optionalString cfg.zfs '' 584 auth optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes} 585 '' + 586 optionalString cfg.pamMount '' 587 auth optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive 588 '' + 589 optionalString cfg.enableKwallet '' 590 auth optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5 591 '' + 592 optionalString cfg.enableGnomeKeyring '' 593 auth optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so 594 '' + 595 optionalString cfg.gnupg.enable '' 596 auth optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so ${optionalString cfg.gnupg.storeOnly " store-only"} 597 '' + 598 optionalString cfg.failDelay.enable '' 599 auth optional ${pkgs.pam}/lib/security/pam_faildelay.so delay=${toString cfg.failDelay.delay} 600 '' + 601 optionalString cfg.googleAuthenticator.enable '' 602 auth required ${pkgs.google-authenticator}/lib/security/pam_google_authenticator.so no_increment_hotp 603 '' + 604 optionalString cfg.duoSecurity.enable '' 605 auth required ${pkgs.duo-unix}/lib/security/pam_duo.so 606 '' 607 )) + 608 optionalString config.services.homed.enable '' 609 auth sufficient ${config.systemd.package}/lib/security/pam_systemd_home.so 610 '' + 611 optionalString cfg.unixAuth '' 612 auth sufficient pam_unix.so ${optionalString cfg.allowNullPassword "nullok"} ${optionalString cfg.nodelay "nodelay"} likeauth try_first_pass 613 '' + 614 optionalString cfg.otpwAuth '' 615 auth sufficient ${pkgs.otpw}/lib/security/pam_otpw.so 616 '' + 617 optionalString use_ldap '' 618 auth sufficient ${pam_ldap}/lib/security/pam_ldap.so use_first_pass 619 '' + 620 optionalString config.services.sssd.enable '' 621 auth sufficient ${pkgs.sssd}/lib/security/pam_sss.so use_first_pass 622 '' + 623 optionalString config.security.pam.krb5.enable '' 624 auth [default=ignore success=1 service_err=reset] ${pam_krb5}/lib/security/pam_krb5.so use_first_pass 625 auth [default=die success=done] ${pam_ccreds}/lib/security/pam_ccreds.so action=validate use_first_pass 626 auth sufficient ${pam_ccreds}/lib/security/pam_ccreds.so action=store use_first_pass 627 '' + 628 '' 629 auth required pam_deny.so 630 631 # Password management. 632 '' + 633 optionalString config.services.homed.enable '' 634 password sufficient ${config.systemd.package}/lib/security/pam_systemd_home.so 635 '' + '' 636 password sufficient pam_unix.so nullok yescrypt 637 '' + 638 optionalString config.security.pam.enableEcryptfs '' 639 password optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so 640 '' + 641 optionalString config.security.pam.enableFscrypt '' 642 password optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so 643 '' + 644 optionalString cfg.zfs '' 645 password optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes} 646 '' + 647 optionalString cfg.pamMount '' 648 password optional ${pkgs.pam_mount}/lib/security/pam_mount.so 649 '' + 650 optionalString use_ldap '' 651 password sufficient ${pam_ldap}/lib/security/pam_ldap.so 652 '' + 653 optionalString cfg.mysqlAuth '' 654 password sufficient ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf 655 '' + 656 optionalString config.services.sssd.enable '' 657 password sufficient ${pkgs.sssd}/lib/security/pam_sss.so 658 '' + 659 optionalString config.security.pam.krb5.enable '' 660 password sufficient ${pam_krb5}/lib/security/pam_krb5.so use_first_pass 661 '' + 662 optionalString cfg.enableGnomeKeyring '' 663 password optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so use_authtok 664 '' + 665 '' 666 667 # Session management. 668 '' + 669 optionalString cfg.setEnvironment '' 670 session required pam_env.so conffile=/etc/pam/environment readenv=0 671 '' + 672 '' 673 session required pam_unix.so 674 '' + 675 optionalString cfg.setLoginUid '' 676 session ${if config.boot.isContainer then "optional" else "required"} pam_loginuid.so 677 '' + 678 optionalString cfg.ttyAudit.enable (concatStringsSep " \\\n " ([ 679 "session required ${pkgs.pam}/lib/security/pam_tty_audit.so" 680 ] ++ optional cfg.ttyAudit.openOnly "open_only" 681 ++ optional (cfg.ttyAudit.enablePattern != null) "enable=${cfg.ttyAudit.enablePattern}" 682 ++ optional (cfg.ttyAudit.disablePattern != null) "disable=${cfg.ttyAudit.disablePattern}" 683 )) + 684 optionalString config.services.homed.enable '' 685 session required ${config.systemd.package}/lib/security/pam_systemd_home.so 686 '' + 687 optionalString cfg.makeHomeDir '' 688 session required ${pkgs.pam}/lib/security/pam_mkhomedir.so silent skel=${config.security.pam.makeHomeDir.skelDirectory} umask=0077 689 '' + 690 optionalString cfg.updateWtmp '' 691 session required ${pkgs.pam}/lib/security/pam_lastlog.so silent 692 '' + 693 optionalString config.security.pam.enableEcryptfs '' 694 session optional ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so 695 '' + 696 optionalString config.security.pam.enableFscrypt '' 697 # Work around https://github.com/systemd/systemd/issues/8598 698 # Skips the pam_fscrypt module for systemd-user sessions which do not have a password 699 # anyways. 700 # See also https://github.com/google/fscrypt/issues/95 701 session [success=1 default=ignore] pam_succeed_if.so service = systemd-user 702 session optional ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so 703 '' + 704 optionalString cfg.zfs '' 705 session [success=1 default=ignore] pam_succeed_if.so service = systemd-user 706 session optional ${config.boot.zfs.package}/lib/security/pam_zfs_key.so homes=${config.security.pam.zfs.homes} ${optionalString config.security.pam.zfs.noUnmount "nounmount"} 707 '' + 708 optionalString cfg.pamMount '' 709 session optional ${pkgs.pam_mount}/lib/security/pam_mount.so disable_interactive 710 '' + 711 optionalString use_ldap '' 712 session optional ${pam_ldap}/lib/security/pam_ldap.so 713 '' + 714 optionalString cfg.mysqlAuth '' 715 session optional ${pkgs.pam_mysql}/lib/security/pam_mysql.so config_file=/etc/security/pam_mysql.conf 716 '' + 717 optionalString config.services.sssd.enable '' 718 session optional ${pkgs.sssd}/lib/security/pam_sss.so 719 '' + 720 optionalString config.security.pam.krb5.enable '' 721 session optional ${pam_krb5}/lib/security/pam_krb5.so 722 '' + 723 optionalString cfg.otpwAuth '' 724 session optional ${pkgs.otpw}/lib/security/pam_otpw.so 725 '' + 726 optionalString cfg.startSession '' 727 session optional ${config.systemd.package}/lib/security/pam_systemd.so 728 '' + 729 optionalString cfg.forwardXAuth '' 730 session optional pam_xauth.so xauthpath=${pkgs.xorg.xauth}/bin/xauth systemuser=99 731 '' + 732 optionalString (cfg.limits != []) '' 733 session required ${pkgs.pam}/lib/security/pam_limits.so conf=${makeLimitsConf cfg.limits} 734 '' + 735 optionalString (cfg.showMotd && (config.users.motd != null || config.users.motdFile != null)) '' 736 session optional ${pkgs.pam}/lib/security/pam_motd.so motd=${motd} 737 '' + 738 optionalString (cfg.enableAppArmor && config.security.apparmor.enable) '' 739 session optional ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so order=user,group,default debug 740 '' + 741 optionalString (cfg.enableKwallet) '' 742 session optional ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so kwalletd=${pkgs.plasma5Packages.kwallet.bin}/bin/kwalletd5 743 '' + 744 optionalString (cfg.enableGnomeKeyring) '' 745 session optional ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so auto_start 746 '' + 747 optionalString cfg.gnupg.enable '' 748 session optional ${pkgs.pam_gnupg}/lib/security/pam_gnupg.so ${optionalString cfg.gnupg.noAutostart " no-autostart"} 749 '' + 750 optionalString (config.virtualisation.lxc.lxcfs.enable) '' 751 session optional ${pkgs.lxc}/lib/security/pam_cgfs.so -c all 752 '' 753 ); 754 }; 755 756 }; 757 758 759 inherit (pkgs) pam_krb5 pam_ccreds; 760 761 use_ldap = (config.users.ldap.enable && config.users.ldap.loginPam); 762 pam_ldap = if config.users.ldap.daemon.enable then pkgs.nss_pam_ldapd else pkgs.pam_ldap; 763 764 # Create a limits.conf(5) file. 765 makeLimitsConf = limits: 766 pkgs.writeText "limits.conf" 767 (concatMapStrings ({ domain, type, item, value }: 768 "${domain} ${type} ${item} ${toString value}\n") 769 limits); 770 771 limitsType = with lib.types; listOf (submodule ({ ... }: { 772 options = { 773 domain = mkOption { 774 description = lib.mdDoc "Username, groupname, or wildcard this limit applies to"; 775 example = "@wheel"; 776 type = str; 777 }; 778 779 type = mkOption { 780 description = lib.mdDoc "Type of this limit"; 781 type = enum [ "-" "hard" "soft" ]; 782 default = "-"; 783 }; 784 785 item = mkOption { 786 description = lib.mdDoc "Item this limit applies to"; 787 type = enum [ 788 "core" 789 "data" 790 "fsize" 791 "memlock" 792 "nofile" 793 "rss" 794 "stack" 795 "cpu" 796 "nproc" 797 "as" 798 "maxlogins" 799 "maxsyslogins" 800 "priority" 801 "locks" 802 "sigpending" 803 "msgqueue" 804 "nice" 805 "rtprio" 806 ]; 807 }; 808 809 value = mkOption { 810 description = lib.mdDoc "Value of this limit"; 811 type = oneOf [ str int ]; 812 }; 813 }; 814 })); 815 816 motd = if config.users.motdFile == null 817 then pkgs.writeText "motd" config.users.motd 818 else config.users.motdFile; 819 820 makePAMService = name: service: 821 { name = "pam.d/${name}"; 822 value.source = pkgs.writeText "${name}.pam" service.text; 823 }; 824 825in 826 827{ 828 829 imports = [ 830 (mkRenamedOptionModule [ "security" "pam" "enableU2F" ] [ "security" "pam" "u2f" "enable" ]) 831 ]; 832 833 ###### interface 834 835 options = { 836 837 security.pam.loginLimits = mkOption { 838 default = []; 839 type = limitsType; 840 example = 841 [ { domain = "ftp"; 842 type = "hard"; 843 item = "nproc"; 844 value = "0"; 845 } 846 { domain = "@student"; 847 type = "-"; 848 item = "maxlogins"; 849 value = "4"; 850 } 851 ]; 852 853 description = lib.mdDoc '' 854 Define resource limits that should apply to users or groups. 855 Each item in the list should be an attribute set with a 856 {var}`domain`, {var}`type`, 857 {var}`item`, and {var}`value` 858 attribute. The syntax and semantics of these attributes 859 must be that described in {manpage}`limits.conf(5)`. 860 861 Note that these limits do not apply to systemd services, 862 whose limits can be changed via {option}`systemd.extraConfig` 863 instead. 864 ''; 865 }; 866 867 security.pam.services = mkOption { 868 default = {}; 869 type = with types; attrsOf (submodule pamOpts); 870 description = 871 lib.mdDoc '' 872 This option defines the PAM services. A service typically 873 corresponds to a program that uses PAM, 874 e.g. {command}`login` or {command}`passwd`. 875 Each attribute of this set defines a PAM service, with the attribute name 876 defining the name of the service. 877 ''; 878 }; 879 880 security.pam.makeHomeDir.skelDirectory = mkOption { 881 type = types.str; 882 default = "/var/empty"; 883 example = "/etc/skel"; 884 description = lib.mdDoc '' 885 Path to skeleton directory whose contents are copied to home 886 directories newly created by `pam_mkhomedir`. 887 ''; 888 }; 889 890 security.pam.enableSSHAgentAuth = mkOption { 891 type = types.bool; 892 default = false; 893 description = 894 lib.mdDoc '' 895 Enable sudo logins if the user's SSH agent provides a key 896 present in {file}`~/.ssh/authorized_keys`. 897 This allows machines to exclusively use SSH keys instead of 898 passwords. 899 ''; 900 }; 901 902 security.pam.enableOTPW = mkEnableOption (lib.mdDoc "the OTPW (one-time password) PAM module"); 903 904 security.pam.krb5 = { 905 enable = mkOption { 906 default = config.krb5.enable; 907 defaultText = literalExpression "config.krb5.enable"; 908 type = types.bool; 909 description = lib.mdDoc '' 910 Enables Kerberos PAM modules (`pam-krb5`, 911 `pam-ccreds`). 912 913 If set, users can authenticate with their Kerberos password. 914 This requires a valid Kerberos configuration 915 (`config.krb5.enable` should be set to 916 `true`). 917 918 Note that the Kerberos PAM modules are not necessary when using SSS 919 to handle Kerberos authentication. 920 ''; 921 }; 922 }; 923 924 security.pam.p11 = { 925 enable = mkOption { 926 default = false; 927 type = types.bool; 928 description = lib.mdDoc '' 929 Enables P11 PAM (`pam_p11`) module. 930 931 If set, users can log in with SSH keys and PKCS#11 tokens. 932 933 More information can be found [here](https://github.com/OpenSC/pam_p11). 934 ''; 935 }; 936 937 control = mkOption { 938 default = "sufficient"; 939 type = types.enum [ "required" "requisite" "sufficient" "optional" ]; 940 description = lib.mdDoc '' 941 This option sets pam "control". 942 If you want to have multi factor authentication, use "required". 943 If you want to use the PKCS#11 device instead of the regular password, 944 use "sufficient". 945 946 Read 947 {manpage}`pam.conf(5)` 948 for better understanding of this option. 949 ''; 950 }; 951 }; 952 953 security.pam.u2f = { 954 enable = mkOption { 955 default = false; 956 type = types.bool; 957 description = lib.mdDoc '' 958 Enables U2F PAM (`pam-u2f`) module. 959 960 If set, users listed in 961 {file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or 962 {file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is 963 not set) are able to log in with the associated U2F key. The path can 964 be changed using {option}`security.pam.u2f.authFile` option. 965 966 File format is: 967 `username:first_keyHandle,first_public_key: second_keyHandle,second_public_key` 968 This file can be generated using {command}`pamu2fcfg` command. 969 970 More information can be found [here](https://developers.yubico.com/pam-u2f/). 971 ''; 972 }; 973 974 authFile = mkOption { 975 default = null; 976 type = with types; nullOr path; 977 description = lib.mdDoc '' 978 By default `pam-u2f` module reads the keys from 979 {file}`$XDG_CONFIG_HOME/Yubico/u2f_keys` (or 980 {file}`$HOME/.config/Yubico/u2f_keys` if XDG variable is 981 not set). 982 983 If you want to change auth file locations or centralize database (for 984 example use {file}`/etc/u2f-mappings`) you can set this 985 option. 986 987 File format is: 988 `username:first_keyHandle,first_public_key: second_keyHandle,second_public_key` 989 This file can be generated using {command}`pamu2fcfg` command. 990 991 More information can be found [here](https://developers.yubico.com/pam-u2f/). 992 ''; 993 }; 994 995 appId = mkOption { 996 default = null; 997 type = with types; nullOr str; 998 description = lib.mdDoc '' 999 By default `pam-u2f` module sets the application 1000 ID to `pam://$HOSTNAME`. 1001 1002 When using {command}`pamu2fcfg`, you can specify your 1003 application ID with the `-i` flag. 1004 1005 More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html) 1006 ''; 1007 }; 1008 1009 origin = mkOption { 1010 default = null; 1011 type = with types; nullOr str; 1012 description = lib.mdDoc '' 1013 By default `pam-u2f` module sets the origin 1014 to `pam://$HOSTNAME`. 1015 Setting origin to an host independent value will allow you to 1016 reuse credentials across machines 1017 1018 When using {command}`pamu2fcfg`, you can specify your 1019 application ID with the `-o` flag. 1020 1021 More information can be found [here](https://developers.yubico.com/pam-u2f/Manuals/pam_u2f.8.html) 1022 ''; 1023 }; 1024 1025 control = mkOption { 1026 default = "sufficient"; 1027 type = types.enum [ "required" "requisite" "sufficient" "optional" ]; 1028 description = lib.mdDoc '' 1029 This option sets pam "control". 1030 If you want to have multi factor authentication, use "required". 1031 If you want to use U2F device instead of regular password, use "sufficient". 1032 1033 Read 1034 {manpage}`pam.conf(5)` 1035 for better understanding of this option. 1036 ''; 1037 }; 1038 1039 debug = mkOption { 1040 default = false; 1041 type = types.bool; 1042 description = lib.mdDoc '' 1043 Debug output to stderr. 1044 ''; 1045 }; 1046 1047 interactive = mkOption { 1048 default = false; 1049 type = types.bool; 1050 description = lib.mdDoc '' 1051 Set to prompt a message and wait before testing the presence of a U2F device. 1052 Recommended if your device doesnt have a tactile trigger. 1053 ''; 1054 }; 1055 1056 cue = mkOption { 1057 default = false; 1058 type = types.bool; 1059 description = lib.mdDoc '' 1060 By default `pam-u2f` module does not inform user 1061 that he needs to use the u2f device, it just waits without a prompt. 1062 1063 If you set this option to `true`, 1064 `cue` option is added to `pam-u2f` 1065 module and reminder message will be displayed. 1066 ''; 1067 }; 1068 }; 1069 1070 security.pam.ussh = { 1071 enable = mkOption { 1072 default = false; 1073 type = types.bool; 1074 description = lib.mdDoc '' 1075 Enables Uber's USSH PAM (`pam-ussh`) module. 1076 1077 This is similar to `pam-ssh-agent`, except that 1078 the presence of a CA-signed SSH key with a valid principal is checked 1079 instead. 1080 1081 Note that this module must both be enabled using this option and on a 1082 per-PAM-service level as well (using `usshAuth`). 1083 1084 More information can be found [here](https://github.com/uber/pam-ussh). 1085 ''; 1086 }; 1087 1088 caFile = mkOption { 1089 default = null; 1090 type = with types; nullOr path; 1091 description = lib.mdDoc '' 1092 By default `pam-ussh` reads the trusted user CA keys 1093 from {file}`/etc/ssh/trusted_user_ca`. 1094 1095 This should be set the same as your `TrustedUserCAKeys` 1096 option for sshd. 1097 ''; 1098 }; 1099 1100 authorizedPrincipals = mkOption { 1101 default = null; 1102 type = with types; nullOr commas; 1103 description = lib.mdDoc '' 1104 Comma-separated list of authorized principals to permit; if the user 1105 presents a certificate with one of these principals, then they will be 1106 authorized. 1107 1108 Note that `pam-ussh` also requires that the certificate 1109 contain a principal matching the user's username. The principals from 1110 this list are in addition to those principals. 1111 1112 Mutually exclusive with `authorizedPrincipalsFile`. 1113 ''; 1114 }; 1115 1116 authorizedPrincipalsFile = mkOption { 1117 default = null; 1118 type = with types; nullOr path; 1119 description = lib.mdDoc '' 1120 Path to a list of principals; if the user presents a certificate with 1121 one of these principals, then they will be authorized. 1122 1123 Note that `pam-ussh` also requires that the certificate 1124 contain a principal matching the user's username. The principals from 1125 this file are in addition to those principals. 1126 1127 Mutually exclusive with `authorizedPrincipals`. 1128 ''; 1129 }; 1130 1131 group = mkOption { 1132 default = null; 1133 type = with types; nullOr str; 1134 description = lib.mdDoc '' 1135 If set, then the authenticating user must be a member of this group 1136 to use this module. 1137 ''; 1138 }; 1139 1140 control = mkOption { 1141 default = "sufficient"; 1142 type = types.enum [ "required" "requisite" "sufficient" "optional" ]; 1143 description = lib.mdDoc '' 1144 This option sets pam "control". 1145 If you want to have multi factor authentication, use "required". 1146 If you want to use the SSH certificate instead of the regular password, 1147 use "sufficient". 1148 1149 Read 1150 {manpage}`pam.conf(5)` 1151 for better understanding of this option. 1152 ''; 1153 }; 1154 }; 1155 1156 security.pam.yubico = { 1157 enable = mkOption { 1158 default = false; 1159 type = types.bool; 1160 description = lib.mdDoc '' 1161 Enables Yubico PAM (`yubico-pam`) module. 1162 1163 If set, users listed in 1164 {file}`~/.yubico/authorized_yubikeys` 1165 are able to log in with the associated Yubikey tokens. 1166 1167 The file must have only one line: 1168 `username:yubikey_token_id1:yubikey_token_id2` 1169 More information can be found [here](https://developers.yubico.com/yubico-pam/). 1170 ''; 1171 }; 1172 control = mkOption { 1173 default = "sufficient"; 1174 type = types.enum [ "required" "requisite" "sufficient" "optional" ]; 1175 description = lib.mdDoc '' 1176 This option sets pam "control". 1177 If you want to have multi factor authentication, use "required". 1178 If you want to use Yubikey instead of regular password, use "sufficient". 1179 1180 Read 1181 {manpage}`pam.conf(5)` 1182 for better understanding of this option. 1183 ''; 1184 }; 1185 id = mkOption { 1186 example = "42"; 1187 type = types.str; 1188 description = lib.mdDoc "client id"; 1189 }; 1190 1191 debug = mkOption { 1192 default = false; 1193 type = types.bool; 1194 description = lib.mdDoc '' 1195 Debug output to stderr. 1196 ''; 1197 }; 1198 mode = mkOption { 1199 default = "client"; 1200 type = types.enum [ "client" "challenge-response" ]; 1201 description = lib.mdDoc '' 1202 Mode of operation. 1203 1204 Use "client" for online validation with a YubiKey validation service such as 1205 the YubiCloud. 1206 1207 Use "challenge-response" for offline validation using YubiKeys with HMAC-SHA-1 1208 Challenge-Response configurations. See the man-page ykpamcfg(1) for further 1209 details on how to configure offline Challenge-Response validation. 1210 1211 More information can be found [here](https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html). 1212 ''; 1213 }; 1214 challengeResponsePath = mkOption { 1215 default = null; 1216 type = types.nullOr types.path; 1217 description = lib.mdDoc '' 1218 If not null, set the path used by yubico pam module where the challenge expected response is stored. 1219 1220 More information can be found [here](https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html). 1221 ''; 1222 }; 1223 }; 1224 1225 security.pam.zfs = { 1226 enable = mkOption { 1227 default = false; 1228 type = types.bool; 1229 description = lib.mdDoc '' 1230 Enable unlocking and mounting of encrypted ZFS home dataset at login. 1231 ''; 1232 }; 1233 1234 homes = mkOption { 1235 example = "rpool/home"; 1236 default = "rpool/home"; 1237 type = types.str; 1238 description = lib.mdDoc '' 1239 Prefix of home datasets. This value will be concatenated with 1240 `"/" + <username>` in order to determine the home dataset to unlock. 1241 ''; 1242 }; 1243 1244 noUnmount = mkOption { 1245 default = false; 1246 type = types.bool; 1247 description = lib.mdDoc '' 1248 Do not unmount home dataset on logout. 1249 ''; 1250 }; 1251 }; 1252 1253 security.pam.enableEcryptfs = mkEnableOption (lib.mdDoc "eCryptfs PAM module (mounting ecryptfs home directory on login)"); 1254 security.pam.enableFscrypt = mkEnableOption (lib.mdDoc '' 1255 Enables fscrypt to automatically unlock directories with the user's login password. 1256 1257 This also enables a service at security.pam.services.fscrypt which is used by 1258 fscrypt to verify the user's password when setting up a new protector. If you 1259 use something other than pam_unix to verify user passwords, please remember to 1260 adjust this PAM service. 1261 ''); 1262 1263 users.motd = mkOption { 1264 default = null; 1265 example = "Today is Sweetmorn, the 4th day of The Aftermath in the YOLD 3178."; 1266 type = types.nullOr types.lines; 1267 description = lib.mdDoc "Message of the day shown to users when they log in."; 1268 }; 1269 1270 users.motdFile = mkOption { 1271 default = null; 1272 example = "/etc/motd"; 1273 type = types.nullOr types.path; 1274 description = lib.mdDoc "A file containing the message of the day shown to users when they log in."; 1275 }; 1276 }; 1277 1278 1279 ###### implementation 1280 1281 config = { 1282 assertions = [ 1283 { 1284 assertion = config.users.motd == null || config.users.motdFile == null; 1285 message = '' 1286 Only one of users.motd and users.motdFile can be set. 1287 ''; 1288 } 1289 { 1290 assertion = config.security.pam.zfs.enable -> (config.boot.zfs.enabled || config.boot.zfs.enableUnstable); 1291 message = '' 1292 `security.pam.zfs.enable` requires enabling ZFS (`boot.zfs.enabled` or `boot.zfs.enableUnstable`). 1293 ''; 1294 } 1295 ]; 1296 1297 environment.systemPackages = 1298 # Include the PAM modules in the system path mostly for the manpages. 1299 [ pkgs.pam ] 1300 ++ optional config.users.ldap.enable pam_ldap 1301 ++ optional config.services.sssd.enable pkgs.sssd 1302 ++ optionals config.security.pam.krb5.enable [pam_krb5 pam_ccreds] 1303 ++ optionals config.security.pam.enableOTPW [ pkgs.otpw ] 1304 ++ optionals config.security.pam.oath.enable [ pkgs.oath-toolkit ] 1305 ++ optionals config.security.pam.p11.enable [ pkgs.pam_p11 ] 1306 ++ optionals config.security.pam.enableFscrypt [ pkgs.fscrypt-experimental ] 1307 ++ optionals config.security.pam.u2f.enable [ pkgs.pam_u2f ]; 1308 1309 boot.supportedFilesystems = optionals config.security.pam.enableEcryptfs [ "ecryptfs" ]; 1310 1311 security.wrappers = { 1312 unix_chkpwd = { 1313 setuid = true; 1314 owner = "root"; 1315 group = "root"; 1316 source = "${pkgs.pam}/bin/unix_chkpwd"; 1317 }; 1318 }; 1319 1320 environment.etc = mapAttrs' makePAMService config.security.pam.services; 1321 1322 security.pam.services = 1323 { other.text = 1324 '' 1325 auth required pam_warn.so 1326 auth required pam_deny.so 1327 account required pam_warn.so 1328 account required pam_deny.so 1329 password required pam_warn.so 1330 password required pam_deny.so 1331 session required pam_warn.so 1332 session required pam_deny.so 1333 ''; 1334 1335 # Most of these should be moved to specific modules. 1336 i3lock = {}; 1337 i3lock-color = {}; 1338 vlock = {}; 1339 xlock = {}; 1340 xscreensaver = {}; 1341 1342 runuser = { rootOK = true; unixAuth = false; setEnvironment = false; }; 1343 1344 /* FIXME: should runuser -l start a systemd session? Currently 1345 it complains "Cannot create session: Already running in a 1346 session". */ 1347 runuser-l = { rootOK = true; unixAuth = false; }; 1348 } // optionalAttrs (config.security.pam.enableFscrypt) { 1349 # Allow fscrypt to verify login passphrase 1350 fscrypt = {}; 1351 }; 1352 1353 security.apparmor.includes."abstractions/pam" = let 1354 isEnabled = test: fold or false (map test (attrValues config.security.pam.services)); 1355 in 1356 lib.concatMapStrings 1357 (name: "r ${config.environment.etc."pam.d/${name}".source},\n") 1358 (attrNames config.security.pam.services) + 1359 '' 1360 mr ${getLib pkgs.pam}/lib/security/pam_filter/*, 1361 mr ${getLib pkgs.pam}/lib/security/pam_*.so, 1362 r ${getLib pkgs.pam}/lib/security/, 1363 '' + 1364 optionalString use_ldap '' 1365 mr ${pam_ldap}/lib/security/pam_ldap.so, 1366 '' + 1367 optionalString config.services.sssd.enable '' 1368 mr ${pkgs.sssd}/lib/security/pam_sss.so, 1369 '' + 1370 optionalString config.security.pam.krb5.enable '' 1371 mr ${pam_krb5}/lib/security/pam_krb5.so, 1372 mr ${pam_ccreds}/lib/security/pam_ccreds.so, 1373 '' + 1374 optionalString (isEnabled (cfg: cfg.googleOsLoginAccountVerification)) '' 1375 mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so, 1376 mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_admin.so, 1377 '' + 1378 optionalString (isEnabled (cfg: cfg.googleOsLoginAuthentication)) '' 1379 mr ${pkgs.google-guest-oslogin}/lib/security/pam_oslogin_login.so, 1380 '' + 1381 optionalString (config.security.pam.enableSSHAgentAuth 1382 && isEnabled (cfg: cfg.sshAgentAuth)) '' 1383 mr ${pkgs.pam_ssh_agent_auth}/libexec/pam_ssh_agent_auth.so, 1384 '' + 1385 optionalString (isEnabled (cfg: cfg.fprintAuth)) '' 1386 mr ${pkgs.fprintd}/lib/security/pam_fprintd.so, 1387 '' + 1388 optionalString (isEnabled (cfg: cfg.u2fAuth)) '' 1389 mr ${pkgs.pam_u2f}/lib/security/pam_u2f.so, 1390 '' + 1391 optionalString (isEnabled (cfg: cfg.usbAuth)) '' 1392 mr ${pkgs.pam_usb}/lib/security/pam_usb.so, 1393 '' + 1394 optionalString (isEnabled (cfg: cfg.usshAuth)) '' 1395 mr ${pkgs.pam_ussh}/lib/security/pam_ussh.so, 1396 '' + 1397 optionalString (isEnabled (cfg: cfg.oathAuth)) '' 1398 "mr ${pkgs.oath-toolkit}/lib/security/pam_oath.so, 1399 '' + 1400 optionalString (isEnabled (cfg: cfg.mysqlAuth)) '' 1401 mr ${pkgs.pam_mysql}/lib/security/pam_mysql.so, 1402 '' + 1403 optionalString (isEnabled (cfg: cfg.yubicoAuth)) '' 1404 mr ${pkgs.yubico-pam}/lib/security/pam_yubico.so, 1405 '' + 1406 optionalString (isEnabled (cfg: cfg.duoSecurity.enable)) '' 1407 mr ${pkgs.duo-unix}/lib/security/pam_duo.so, 1408 '' + 1409 optionalString (isEnabled (cfg: cfg.otpwAuth)) '' 1410 mr ${pkgs.otpw}/lib/security/pam_otpw.so, 1411 '' + 1412 optionalString config.security.pam.enableEcryptfs '' 1413 mr ${pkgs.ecryptfs}/lib/security/pam_ecryptfs.so, 1414 '' + 1415 optionalString config.security.pam.enableFscrypt '' 1416 mr ${pkgs.fscrypt-experimental}/lib/security/pam_fscrypt.so, 1417 '' + 1418 optionalString (isEnabled (cfg: cfg.pamMount)) '' 1419 mr ${pkgs.pam_mount}/lib/security/pam_mount.so, 1420 '' + 1421 optionalString (isEnabled (cfg: cfg.enableGnomeKeyring)) '' 1422 mr ${pkgs.gnome.gnome-keyring}/lib/security/pam_gnome_keyring.so, 1423 '' + 1424 optionalString (isEnabled (cfg: cfg.startSession)) '' 1425 mr ${config.systemd.package}/lib/security/pam_systemd.so, 1426 '' + 1427 optionalString (isEnabled (cfg: cfg.enableAppArmor) 1428 && config.security.apparmor.enable) '' 1429 mr ${pkgs.apparmor-pam}/lib/security/pam_apparmor.so, 1430 '' + 1431 optionalString (isEnabled (cfg: cfg.enableKwallet)) '' 1432 mr ${pkgs.plasma5Packages.kwallet-pam}/lib/security/pam_kwallet5.so, 1433 '' + 1434 optionalString config.virtualisation.lxc.lxcfs.enable '' 1435 mr ${pkgs.lxc}/lib/security/pam_cgfs.so, 1436 '' + 1437 optionalString (isEnabled (cfg: cfg.zfs)) '' 1438 mr ${config.boot.zfs.package}/lib/security/pam_zfs_key.so, 1439 '' + 1440 optionalString config.services.homed.enable '' 1441 mr ${config.systemd.package}/lib/security/pam_systemd_home.so 1442 ''; 1443 }; 1444 1445}