vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / security / pam_mount.nix
blobbc0c5c5fbfbc3346945c125df9912b9e8709818f
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.security.pam.mount;
8   oflRequired = cfg.logoutHup || cfg.logoutTerm || cfg.logoutKill;
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   '';
16   anyPamMount = any (attrByPath ["pamMount"] false) (attrValues config.security.pam.services);
20   options = {
22     security.pam.mount = {
23       enable = mkOption {
24         type = types.bool;
25         default = false;
26         description = ''
27           Enable PAM mount system to mount filesystems on user login.
28         '';
29       };
31       extraVolumes = mkOption {
32         type = types.listOf types.str;
33         default = [];
34         description = ''
35           List of volume definitions for pam_mount.
36           For more information, visit <https://pam-mount.sourceforge.net/pam_mount.conf.5.html>.
37         '';
38       };
40       additionalSearchPaths = mkOption {
41         type = types.listOf types.package;
42         default = [];
43         example = literalExpression "[ pkgs.bindfs ]";
44         description = ''
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       };
50       cryptMountOptions = mkOption {
51         type = types.listOf types.str;
52         default = [];
53         example = literalExpression ''
54           [ "allow_discard" ]
55         '';
56         description = ''
57           Global mount options that apply to every crypt volume.
58           You can define volume-specific options in the volume definitions.
59         '';
60       };
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 = ''
69           Global mount options that apply to every FUSE volume.
70           You can define volume-specific options in the volume definitions.
71         '';
72       };
74       debugLevel = mkOption {
75         type = types.int;
76         default = 0;
77         example = 1;
78         description = ''
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 <https://pam-mount.sourceforge.net/pam_mount.conf.5.html>.
82         '';
83       };
85       logoutWait = mkOption {
86         type = types.int;
87         default = 0;
88         description = ''
89           Amount of microseconds to wait until killing remaining processes after
90           final logout.
91           For more information, visit <https://pam-mount.sourceforge.net/pam_mount.conf.5.html>.
92         '';
93       };
95       logoutHup = mkOption {
96         type = types.bool;
97         default = false;
98         description = ''
99           Kill remaining processes after logout by sending a SIGHUP.
100         '';
101       };
103       logoutTerm = mkOption {
104         type = types.bool;
105         default = false;
106         description = ''
107           Kill remaining processes after logout by sending a SIGTERM.
108         '';
109       };
111       logoutKill = mkOption {
112         type = types.bool;
113         default = false;
114         description = ''
115           Kill remaining processes after logout by sending a SIGKILL.
116         '';
117       };
119       createMountPoints = mkOption {
120         type = types.bool;
121         default = true;
122         description = ''
123           Create mountpoints for volumes if they do not exist.
124         '';
125       };
127       removeCreatedMountPoints = mkOption {
128         type = types.bool;
129         default = true;
130         description = ''
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     };
138   };
140   config = mkIf (cfg.enable || anyPamMount) {
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           <!-- the comma in front of the options is necessary for empty options -->
171           <fusemount>${pkgs.fuse}/bin/mount.fuse %(VOLUME) %(MNTPT) -o ,${concatStringsSep "," (cfg.fuseMountOptions ++ [ "%(OPTIONS)" ])}'</fusemount>
172           <fuseumount>${pkgs.fuse}/bin/fusermount -u %(MNTPT)</fuseumount>
173           <!-- the comma in front of the options is necessary for empty options -->
174           <cryptmount>${pkgs.pam_mount}/bin/mount.crypt -o ,${concatStringsSep "," (cfg.cryptMountOptions ++ [ "%(OPTIONS)" ])} %(VOLUME) %(MNTPT)</cryptmount>
175           <cryptumount>${pkgs.pam_mount}/bin/umount.crypt %(MNTPT)</cryptumount>
176           <pmvarrun>${pkgs.pam_mount}/bin/pmvarrun -u %(USER) -o %(OPERATION)</pmvarrun>
177           ${optionalString oflRequired "<ofl>${fake_ofl}/bin/fake_ofl %(SIGNAL) %(MNTPT)</ofl>"}
178           ${concatStrings (map userVolumeEntry (attrValues extraUserVolumes))}
179           ${concatStringsSep "\n" cfg.extraVolumes}
180           </pam_mount>
181           '';
182     };
184   };