at 23.11-pre 6.7 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.security.pam.mount; 7 8 oflRequired = cfg.logoutHup || cfg.logoutTerm || cfg.logoutKill; 9 10 fake_ofl = pkgs.writeShellScriptBin "fake_ofl" '' 11 SIGNAL=$1 12 MNTPT=$2 13 ${pkgs.lsof}/bin/lsof | ${pkgs.gnugrep}/bin/grep $MNTPT | ${pkgs.gawk}/bin/awk '{print $2}' | ${pkgs.findutils}/bin/xargs ${pkgs.util-linux}/bin/kill -$SIGNAL 14 ''; 15 16 anyPamMount = any (attrByPath ["pamMount"] false) (attrValues config.security.pam.services); 17in 18 19{ 20 options = { 21 22 security.pam.mount = { 23 enable = mkOption { 24 type = types.bool; 25 default = false; 26 description = lib.mdDoc '' 27 Enable PAM mount system to mount filesystems on user login. 28 ''; 29 }; 30 31 extraVolumes = mkOption { 32 type = types.listOf types.str; 33 default = []; 34 description = lib.mdDoc '' 35 List of volume definitions for pam_mount. 36 For more information, visit <http://pam-mount.sourceforge.net/pam_mount.conf.5.html>. 37 ''; 38 }; 39 40 additionalSearchPaths = mkOption { 41 type = types.listOf types.package; 42 default = []; 43 example = literalExpression "[ pkgs.bindfs ]"; 44 description = lib.mdDoc '' 45 Additional programs to include in the search path of pam_mount. 46 Useful for example if you want to use some FUSE filesystems like bindfs. 47 ''; 48 }; 49 50 cryptMountOptions = mkOption { 51 type = types.listOf types.str; 52 default = []; 53 example = literalExpression '' 54 [ "allow_discard" ] 55 ''; 56 description = lib.mdDoc '' 57 Global mount options that apply to every crypt volume. 58 You can define volume-specific options in the volume definitions. 59 ''; 60 }; 61 62 fuseMountOptions = mkOption { 63 type = types.listOf types.str; 64 default = []; 65 example = literalExpression '' 66 [ "nodev" "nosuid" "force-user=%(USER)" "gid=%(USERGID)" "perms=0700" "chmod-deny" "chown-deny" "chgrp-deny" ] 67 ''; 68 description = lib.mdDoc '' 69 Global mount options that apply to every FUSE volume. 70 You can define volume-specific options in the volume definitions. 71 ''; 72 }; 73 74 debugLevel = mkOption { 75 type = types.int; 76 default = 0; 77 example = 1; 78 description = lib.mdDoc '' 79 Sets the Debug-Level. 0 disables debugging, 1 enables pam_mount tracing, 80 and 2 additionally enables tracing in mount.crypt. The default is 0. 81 For more information, visit <http://pam-mount.sourceforge.net/pam_mount.conf.5.html>. 82 ''; 83 }; 84 85 logoutWait = mkOption { 86 type = types.int; 87 default = 0; 88 description = lib.mdDoc '' 89 Amount of microseconds to wait until killing remaining processes after 90 final logout. 91 For more information, visit <http://pam-mount.sourceforge.net/pam_mount.conf.5.html>. 92 ''; 93 }; 94 95 logoutHup = mkOption { 96 type = types.bool; 97 default = false; 98 description = lib.mdDoc '' 99 Kill remaining processes after logout by sending a SIGHUP. 100 ''; 101 }; 102 103 logoutTerm = mkOption { 104 type = types.bool; 105 default = false; 106 description = lib.mdDoc '' 107 Kill remaining processes after logout by sending a SIGTERM. 108 ''; 109 }; 110 111 logoutKill = mkOption { 112 type = types.bool; 113 default = false; 114 description = lib.mdDoc '' 115 Kill remaining processes after logout by sending a SIGKILL. 116 ''; 117 }; 118 119 createMountPoints = mkOption { 120 type = types.bool; 121 default = true; 122 description = lib.mdDoc '' 123 Create mountpoints for volumes if they do not exist. 124 ''; 125 }; 126 127 removeCreatedMountPoints = mkOption { 128 type = types.bool; 129 default = true; 130 description = lib.mdDoc '' 131 Remove mountpoints created by pam_mount after logout. This 132 only affects mountpoints that have been created by pam_mount 133 in the same session. 134 ''; 135 }; 136 }; 137 138 }; 139 140 config = mkIf (cfg.enable || anyPamMount) { 141 142 environment.systemPackages = [ pkgs.pam_mount ]; 143 environment.etc."security/pam_mount.conf.xml" = { 144 source = 145 let 146 extraUserVolumes = filterAttrs (n: u: u.cryptHomeLuks != null || u.pamMount != {}) config.users.users; 147 mkAttr = k: v: ''${k}="${v}"''; 148 userVolumeEntry = user: let 149 attrs = { 150 user = user.name; 151 path = user.cryptHomeLuks; 152 mountpoint = user.home; 153 } // user.pamMount; 154 in 155 "<volume ${concatStringsSep " " (mapAttrsToList mkAttr attrs)} />\n"; 156 in 157 pkgs.writeText "pam_mount.conf.xml" '' 158 <?xml version="1.0" encoding="utf-8" ?> 159 <!DOCTYPE pam_mount SYSTEM "pam_mount.conf.xml.dtd"> 160 <!-- auto generated from Nixos: modules/config/users-groups.nix --> 161 <pam_mount> 162 <debug enable="${toString cfg.debugLevel}" /> 163 <!-- if activated, requires ofl from hxtools to be present --> 164 <logout wait="${toString cfg.logoutWait}" hup="${if cfg.logoutHup then "yes" else "no"}" term="${if cfg.logoutTerm then "yes" else "no"}" kill="${if cfg.logoutKill then "yes" else "no"}" /> 165 <!-- set PATH variable for pam_mount module --> 166 <path>${makeBinPath ([ pkgs.util-linux ] ++ cfg.additionalSearchPaths)}</path> 167 <!-- create mount point if not present --> 168 <mkmountpoint enable="${if cfg.createMountPoints then "1" else "0"}" remove="${if cfg.removeCreatedMountPoints then "true" else "false"}" /> 169 <!-- specify the binaries to be called --> 170 <fusemount>${pkgs.fuse}/bin/mount.fuse %(VOLUME) %(MNTPT) -o ${concatStringsSep "," (cfg.fuseMountOptions ++ [ "%(OPTIONS)" ])}</fusemount> 171 <fuseumount>${pkgs.fuse}/bin/fusermount -u %(MNTPT)</fuseumount> 172 <cryptmount>${pkgs.pam_mount}/bin/mount.crypt -o ${concatStringsSep "," (cfg.cryptMountOptions ++ [ "%(OPTIONS)" ])} %(VOLUME) %(MNTPT)</cryptmount> 173 <cryptumount>${pkgs.pam_mount}/bin/umount.crypt %(MNTPT)</cryptumount> 174 <pmvarrun>${pkgs.pam_mount}/bin/pmvarrun -u %(USER) -o %(OPERATION)</pmvarrun> 175 ${optionalString oflRequired "<ofl>${fake_ofl}/bin/fake_ofl %(SIGNAL) %(MNTPT)</ofl>"} 176 ${concatStrings (map userVolumeEntry (attrValues extraUserVolumes))} 177 ${concatStringsSep "\n" cfg.extraVolumes} 178 </pam_mount> 179 ''; 180 }; 181 182 }; 183}