vuls: init at 0.27.0 (#348530)
[NixPkgs.git] / nixos / modules / services / mail / clamsmtp.nix
blobd40ed7bf6e2ded43aa8f56f33b910ce679df3db2
1 { config, lib, pkgs, ... }:
2 let
3   cfg = config.services.clamsmtp;
4   clamdSocket = "/run/clamav/clamd.ctl"; # See services/security/clamav.nix
5 in
7   ##### interface
8   options = {
9     services.clamsmtp = {
10       enable = lib.mkOption {
11         type = lib.types.bool;
12         default = false;
13         description = "Whether to enable clamsmtp.";
14       };
16       instances = lib.mkOption {
17         description = "Instances of clamsmtp to run.";
18         type = lib.types.listOf (lib.types.submodule { options = {
19           action = lib.mkOption {
20             type = lib.types.enum [ "bounce" "drop" "pass" ];
21             default = "drop";
22             description = ''
23                 Action to take when a virus is detected.
25                 Note that viruses often spoof sender addresses, so bouncing is
26                 in most cases not a good idea.
27               '';
28           };
30           header = lib.mkOption {
31             type = lib.types.str;
32             default = "";
33             example = "X-Virus-Scanned: ClamAV using ClamSMTP";
34             description = ''
35                 A header to add to scanned messages. See clamsmtpd.conf(5) for
36                 more details. Empty means no header.
37               '';
38           };
40           keepAlives = lib.mkOption {
41             type = lib.types.int;
42             default = 0;
43             description = ''
44                 Number of seconds to wait between each NOOP sent to the sending
45                 server. 0 to disable.
47                 This is meant for slow servers where the sending MTA times out
48                 waiting for clamd to scan the file.
49               '';
50           };
52           listen = lib.mkOption {
53             type = lib.types.str;
54             example = "127.0.0.1:10025";
55             description = ''
56                 Address to wait for incoming SMTP connections on. See
57                 clamsmtpd.conf(5) for more details.
58               '';
59           };
61           quarantine = lib.mkOption {
62             type = lib.types.bool;
63             default = false;
64             description = ''
65                 Whether to quarantine files that contain viruses by leaving them
66                 in the temporary directory.
67               '';
68           };
70           maxConnections = lib.mkOption {
71             type = lib.types.int;
72             default = 64;
73             description = "Maximum number of connections to accept at once.";
74           };
76           outAddress = lib.mkOption {
77             type = lib.types.str;
78             description = ''
79                 Address of the SMTP server to send email to once it has been
80                 scanned.
81               '';
82           };
84           tempDirectory = lib.mkOption {
85             type = lib.types.str;
86             default = "/tmp";
87             description = ''
88                 Temporary directory that needs to be accessible to both clamd
89                 and clamsmtpd.
90               '';
91           };
93           timeout = lib.mkOption {
94             type = lib.types.int;
95             default = 180;
96             description = "Time-out for network connections.";
97           };
99           transparentProxy = lib.mkOption {
100             type = lib.types.bool;
101             default = false;
102             description = "Enable clamsmtp's transparent proxy support.";
103           };
105           virusAction = lib.mkOption {
106             type = with lib.types; nullOr path;
107             default = null;
108             description = ''
109                 Command to run when a virus is found. Please see VIRUS ACTION in
110                 clamsmtpd(8) for a discussion of this option and its safe use.
111               '';
112           };
114           xClient = lib.mkOption {
115             type = lib.types.bool;
116             default = false;
117             description = ''
118                 Send the XCLIENT command to the receiving server, for forwarding
119                 client addresses and connection information if the receiving
120                 server supports this feature.
121               '';
122           };
123         };});
124       };
125     };
126   };
128   ##### implementation
129   config = let
130     configfile = conf: pkgs.writeText "clamsmtpd.conf"
131       ''
132         Action: ${conf.action}
133         ClamAddress: ${clamdSocket}
134         Header: ${conf.header}
135         KeepAlives: ${toString conf.keepAlives}
136         Listen: ${conf.listen}
137         Quarantine: ${if conf.quarantine then "on" else "off"}
138         MaxConnections: ${toString conf.maxConnections}
139         OutAddress: ${conf.outAddress}
140         TempDirectory: ${conf.tempDirectory}
141         TimeOut: ${toString conf.timeout}
142         TransparentProxy: ${if conf.transparentProxy then "on" else "off"}
143         User: clamav
144         ${lib.optionalString (conf.virusAction != null) "VirusAction: ${conf.virusAction}"}
145         XClient: ${if conf.xClient then "on" else "off"}
146       '';
147   in
148     lib.mkIf cfg.enable {
149       assertions = [
150         { assertion = config.services.clamav.daemon.enable;
151           message = "clamsmtp requires clamav to be enabled";
152         }
153       ];
155       systemd.services = lib.listToAttrs (lib.imap1 (i: conf:
156         lib.nameValuePair "clamsmtp-${toString i}" {
157           description = "ClamSMTP instance ${toString i}";
158           wantedBy = [ "multi-user.target" ];
159           script = "exec ${pkgs.clamsmtp}/bin/clamsmtpd -f ${configfile conf}";
160           after = [ "clamav-daemon.service" ];
161           requires = [ "clamav-daemon.service" ];
162           serviceConfig.Type = "forking";
163           serviceConfig.PrivateTmp = "yes";
164           unitConfig.JoinsNamespaceOf = "clamav-daemon.service";
165         }
166       ) cfg.instances);
167     };
169   meta.maintainers = with lib.maintainers; [ ekleog ];