]> git.proxmox.com Git - pmg-api.git/blame - PMG/Config.pm
archivemaxrec: add missing property type
[pmg-api.git] / PMG / Config.pm
CommitLineData
7e0e6dbe
DM
1package PMG::Config::Base;
2
3use strict;
4use warnings;
5use Data::Dumper;
6
7use PVE::Tools;
8use PVE::JSONSchema qw(get_standard_option);
9use PVE::SectionConfig;
10
11use base qw(PVE::SectionConfig);
12
13my $defaultData = {
14 propertyList => {
15 type => { description => "Section type." },
ef6f5dd1 16 section => {
7e0e6dbe
DM
17 description => "Secion ID.",
18 type => 'string', format => 'pve-configid',
19 },
20 },
21};
22
23sub private {
24 return $defaultData;
25}
26
27sub format_section_header {
28 my ($class, $type, $sectionId) = @_;
29
30 if ($type eq 'ldap') {
31 $sectionId =~ s/^ldap_//;
32 return "$type: $sectionId\n";
33 } else {
34 return "section: $type\n";
35 }
36}
37
38
39sub parse_section_header {
40 my ($class, $line) = @_;
41
42 if ($line =~ m/^(ldap|section):\s*(\S+)\s*$/) {
43 my ($raw_type, $raw_id) = (lc($1), $2);
44 my $type = $raw_type eq 'section' ? $raw_id : $raw_type;
45 my $section_id = "${raw_type}_${raw_id}";
46 my $errmsg = undef; # set if you want to skip whole section
47 eval { PVE::JSONSchema::pve_verify_configid($raw_id); };
48 $errmsg = $@ if $@;
49 my $config = {}; # to return additional attributes
50 return ($type, $section_id, $errmsg, $config);
51 }
52 return undef;
53}
54
ac5d1312 55package PMG::Config::Admin;
7e0e6dbe
DM
56
57use strict;
58use warnings;
59
60use base qw(PMG::Config::Base);
61
62sub type {
ac5d1312 63 return 'admin';
7e0e6dbe
DM
64}
65
66sub properties {
67 return {
68 dailyreport => {
69 description => "Send daily reports.",
70 type => 'boolean',
71 default => 1,
72 },
f62194b2
DM
73 demo => {
74 description => "Demo mode - do not start SMTP filter.",
75 type => 'boolean',
76 default => 0,
77 },
78 email => {
79 description => "Administrator E-Mail address.",
80 type => 'string', format => 'email',
81 default => 'admin@domain.tld',
ac5d1312
DM
82 },
83 proxyport => {
84 description => "HTTP proxy port.",
85 type => 'integer',
86 minimum => 1,
87 default => 8080,
88 },
89 proxyserver => {
90 description => "HTTP proxy server address.",
91 type => 'string',
92 },
93 proxyuser => {
94 description => "HTTP proxy user name.",
95 type => 'string',
96 },
97 proxypassword => {
98 description => "HTTP proxy password.",
99 type => 'string',
100 },
7e0e6dbe
DM
101 };
102}
103
104sub options {
105 return {
106 dailyreport => { optional => 1 },
f62194b2 107 demo => { optional => 1 },
ac5d1312
DM
108 proxyport => { optional => 1 },
109 proxyserver => { optional => 1 },
110 proxyuser => { optional => 1 },
111 proxypassword => { optional => 1 },
7e0e6dbe
DM
112 };
113}
114
115package PMG::Config::Spam;
116
117use strict;
118use warnings;
119
120use base qw(PMG::Config::Base);
121
122sub type {
123 return 'spam';
124}
125
126sub properties {
127 return {
1ccc8e95
DM
128 languages => {
129 description => "This option is used to specify which languages are considered OK for incoming mail.",
130 type => 'string',
131 pattern => '(all|([a-z][a-z])+( ([a-z][a-z])+)*)',
132 default => 'all',
133 },
134 use_bayes => {
135 description => "Whether to use the naive-Bayesian-style classifier.",
136 type => 'boolean',
137 default => 1,
138 },
582cfacf
DM
139 use_awl => {
140 description => "Use the Auto-Whitelist plugin.",
141 type => 'boolean',
142 default => 1,
143 },
144 use_razor => {
145 description => "Whether to use Razor2, if it is available.",
146 type => 'boolean',
147 default => 1,
148 },
03ac6d8f
DM
149 use_ocr => {
150 description => "Enable OCR to scan pictures.",
151 type => 'boolean',
152 default => 0,
153 },
1ccc8e95
DM
154 wl_bounce_relays => {
155 description => "Whitelist legitimate bounce relays.",
156 type => 'string',
157 },
7e0e6dbe
DM
158 bounce_score => {
159 description => "Additional score for bounce mails.",
160 type => 'integer',
161 minimum => 0,
162 maximum => 1000,
163 default => 0,
164 },
f62194b2
DM
165 rbl_checks => {
166 description => "Enable real time blacklists (RBL) checks.",
167 type => 'boolean',
168 default => 1,
169 },
170 maxspamsize => {
171 description => "Maximum size of spam messages in bytes.",
172 type => 'integer',
4d76e24e 173 minimum => 64,
f62194b2
DM
174 default => 200*1024,
175 },
7e0e6dbe
DM
176 };
177}
178
179sub options {
180 return {
582cfacf
DM
181 use_awl => { optional => 1 },
182 use_razor => { optional => 1 },
03ac6d8f 183 use_ocr => { optional => 1 },
1ccc8e95
DM
184 wl_bounce_relays => { optional => 1 },
185 languages => { optional => 1 },
186 use_bayes => { optional => 1 },
7e0e6dbe 187 bounce_score => { optional => 1 },
f62194b2
DM
188 rbl_checks => { optional => 1 },
189 maxspamsize => { optional => 1 },
190 };
191}
192
193package PMG::Config::ClamAV;
194
195use strict;
196use warnings;
197
198use base qw(PMG::Config::Base);
199
200sub type {
201 return 'clamav';
202}
203
204sub properties {
205 return {
ac5d1312
DM
206 dbmirror => {
207 description => "ClamAV database mirror server.",
208 type => 'string',
209 default => 'database.clamav.net',
210 },
211 archiveblockencrypted => {
212 description => "Wether to block encrypted archives. Mark encrypted archives as viruses.",
213 type => 'boolean',
214 default => 0,
215 },
216 archivemaxrec => {
217 description => "Nested archives are scanned recursively, e.g. if a ZIP archive contains a TAR file, all files within it will also be scanned. This options specifies how deeply the process should be continued. Warning: setting this limit too high may result in severe damage to the system.",
1baec5ab 218 type => 'integer',
ac5d1312
DM
219 minimum => 1,
220 default => 5,
221 },
f62194b2 222 archivemaxfiles => {
ac5d1312 223 description => "Number of files to be scanned within an archive, a document, or any other kind of container. Warning: disabling this limit or setting it too high may result in severe damage to the system.",
f62194b2
DM
224 type => 'integer',
225 minimum => 0,
226 default => 1000,
227 },
ac5d1312
DM
228 archivemaxsize => {
229 description => "Files larger than this limit won't be scanned.",
230 type => 'integer',
231 minimum => 1000000,
232 default => 25000000,
233 },
234 maxscansize => {
235 description => "Sets the maximum amount of data to be scanned for each input file.",
236 type => 'integer',
237 minimum => 1000000,
238 default => 100000000,
239 },
240 maxcccount => {
241 description => "This option sets the lowest number of Credit Card or Social Security numbers found in a file to generate a detect.",
242 type => 'integer',
243 minimum => 0,
244 default => 0,
245 },
f62194b2
DM
246 };
247}
248
249sub options {
250 return {
ac5d1312
DM
251 archiveblockencrypted => { optional => 1 },
252 archivemaxrec => { optional => 1 },
f62194b2 253 archivemaxfiles => { optional => 1 },
ac5d1312
DM
254 archivemaxsize => { optional => 1 },
255 maxscansize => { optional => 1 },
256 dbmirror => { optional => 1 },
257 maxcccount => { optional => 1 },
7e0e6dbe
DM
258 };
259}
260
261package PMG::Config::LDAP;
262
263use strict;
264use warnings;
265
266use base qw(PMG::Config::Base);
267
268sub type {
269 return 'ldap';
270}
271
272sub properties {
273 return {
274 mode => {
275 description => "LDAP protocol mode ('ldap' or 'ldaps').",
276 type => 'string',
277 enum => ['ldap', 'ldaps'],
278 default => 'ldap',
279 },
280 };
281}
282
283sub options {
284 return {
285 mode => { optional => 1 },
286 };
287}
f62194b2 288
d9dc3c08
DM
289package PMG::Config::Mail;
290
291use strict;
292use warnings;
293
f62194b2
DM
294use PVE::ProcFSTools;
295
d9dc3c08
DM
296use base qw(PMG::Config::Base);
297
298sub type {
299 return 'mail';
300}
301
f62194b2
DM
302my $physicalmem = 0;
303sub physical_memory {
304
305 return $physicalmem if $physicalmem;
306
307 my $info = PVE::ProcFSTools::read_meminfo();
308 my $total = int($info->{memtotal} / (1024*1024));
309
310 return $total;
311}
312
313sub get_max_filters {
314 # estimate optimal number of filter servers
315
316 my $max_servers = 5;
317 my $servermem = 120;
318 my $memory = physical_memory();
319 my $add_servers = int(($memory - 512)/$servermem);
320 $max_servers += $add_servers if $add_servers > 0;
321 $max_servers = 40 if $max_servers > 40;
322
323 return $max_servers - 2;
324}
325
f609bf7f
DM
326sub get_max_smtpd {
327 # estimate optimal number of smtpd daemons
328
329 my $max_servers = 25;
330 my $servermem = 20;
331 my $memory = physical_memory();
332 my $add_servers = int(($memory - 512)/$servermem);
333 $max_servers += $add_servers if $add_servers > 0;
334 $max_servers = 100 if $max_servers > 100;
335 return $max_servers;
336}
337
338
d9dc3c08
DM
339sub properties {
340 return {
f609bf7f
DM
341 relay => {
342 description => "The default mail delivery transport (incoming mails).",
343 type => 'string',
344 },
345 relayport => {
346 description => "SMTP port number for relay host.",
347 type => 'integer',
348 minimum => 1,
349 maximum => 65535,
350 default => 25,
351 },
352 relaynomx => {
353 description => "Disable MX lookups for default relay.",
354 type => 'boolean',
355 default => 0,
356 },
357 smarthost => {
358 description => "When set, all outgoing mails are deliverd to the specified smarthost.",
359 type => 'string',
360 },
d9dc3c08
DM
361 banner => {
362 description => "ESMTP banner.",
363 type => 'string',
364 maxLength => 1024,
365 default => 'ESMTP Proxmox',
366 },
f62194b2
DM
367 max_filters => {
368 description => "Maximum number of filter processes.",
369 type => 'integer',
370 minimum => 3,
371 maximum => 40,
372 default => get_max_filters(),
373 },
f609bf7f
DM
374 max_smtpd_in => {
375 description => "Maximum number of SMTP daemon processes (in).",
376 type => 'integer',
377 minimum => 3,
378 maximum => 100,
379 default => get_max_smtpd(),
380 },
381 max_smtpd_out => {
382 description => "Maximum number of SMTP daemon processes (out).",
383 type => 'integer',
384 minimum => 3,
385 maximum => 100,
386 default => get_max_smtpd(),
387 },
388 conn_count_limit => {
389 description => "How many simultaneous connections any client is allowed to make to this service. To disable this feature, specify a limit of 0.",
390 type => 'integer',
391 minimum => 0,
392 default => 50,
393 },
394 conn_rate_limit => {
395 description => "The maximal number of connection attempts any client is allowed to make to this service per minute. To disable this feature, specify a limit of 0.",
396 type => 'integer',
397 minimum => 0,
398 default => 0,
399 },
400 message_rate_limit => {
401 description => "The maximal number of message delivery requests that any client is allowed to make to this service per minute.To disable this feature, specify a limit of 0.",
402 type => 'integer',
403 minimum => 0,
404 default => 0,
405 },
f62194b2
DM
406 hide_received => {
407 description => "Hide received header in outgoing mails.",
408 type => 'boolean',
ac5d1312
DM
409 default => 0,
410 },
f609bf7f 411 maxsize => {
ac5d1312
DM
412 description => "Maximum email size. Larger mails are rejected.",
413 type => 'integer',
414 minimum => 1024,
415 default => 1024*1024*10,
f62194b2 416 },
f609bf7f
DM
417 dwarning => {
418 description => "SMTP delay warning time (in hours).",
419 type => 'integer',
420 minimum => 0,
421 default => 4,
422 },
423 use_rbl => {
4d76e24e 424 description => "Use Realtime Blacklists.",
f609bf7f
DM
425 type => 'boolean',
426 default => 1,
427 },
428 tls => {
4d76e24e 429 description => "Use TLS.",
f609bf7f
DM
430 type => 'boolean',
431 default => 0,
432 },
433 spf => {
4d76e24e 434 description => "Use Sender Policy Framework.",
f609bf7f
DM
435 type => 'boolean',
436 default => 1,
437 },
438 greylist => {
4d76e24e 439 description => "Use Greylisting.",
f609bf7f
DM
440 type => 'boolean',
441 default => 1,
442 },
443 helotests => {
4d76e24e 444 description => "Use SMTP HELO tests.",
f609bf7f
DM
445 type => 'boolean',
446 default => 0,
447 },
448 rejectunknown => {
4d76e24e 449 description => "Reject unknown clients.",
f609bf7f
DM
450 type => 'boolean',
451 default => 0,
452 },
453 rejectunknownsender => {
4d76e24e 454 description => "Reject unknown senders.",
f609bf7f
DM
455 type => 'boolean',
456 default => 0,
457 },
458 verifyreceivers => {
459 description => "Enable receiver verification. The value (if greater than 0) spefifies the numerical reply code when the Postfix SMTP server rejects a recipient address (450 or 550).",
460 type => 'integer',
461 minimum => 0,
462 maximum => 599,
463 default => 0,
464 },
465 dnsbl_sites => {
466 description => "Optional list of DNS white/blacklist domains (see postscreen_dnsbl_sites parameter).",
467 type => 'string',
468 },
d9dc3c08
DM
469 };
470}
471
472sub options {
473 return {
f609bf7f
DM
474 relay => { optional => 1 },
475 relayport => { optional => 1 },
476 relaynomx => { optional => 1 },
477 dwarning => { optional => 1 },
478 max_smtpd_in => { optional => 1 },
479 max_smtpd_out => { optional => 1 },
480 greylist => { optional => 1 },
481 helotests => { optional => 1 },
482 use_rbl => { optional => 1 },
483 tls => { optional => 1 },
484 spf => { optional => 1 },
485 maxsize => { optional => 1 },
d9dc3c08 486 banner => { optional => 1 },
f62194b2
DM
487 max_filters => { optional => 1 },
488 hide_received => { optional => 1 },
f609bf7f
DM
489 rejectunknown => { optional => 1 },
490 rejectunknownsender => { optional => 1 },
491 conn_count_limit => { optional => 1 },
492 conn_rate_limit => { optional => 1 },
493 message_rate_limit => { optional => 1 },
494 verifyreceivers => { optional => 1 },
495 dnsbl_sites => { optional => 1 },
d9dc3c08
DM
496 };
497}
7e0e6dbe
DM
498package PMG::Config;
499
500use strict;
501use warnings;
9123cab5 502use IO::File;
7e0e6dbe 503use Data::Dumper;
4ccdc564 504use Template;
7e0e6dbe 505
9123cab5 506use PVE::SafeSyslog;
7e0e6dbe
DM
507use PVE::Tools;
508use PVE::INotify;
509
4ccdc564
DM
510use PMG::AtomicFile;
511
ac5d1312 512PMG::Config::Admin->register();
d9dc3c08 513PMG::Config::Mail->register();
7e0e6dbe
DM
514PMG::Config::Spam->register();
515PMG::Config::LDAP->register();
f62194b2 516PMG::Config::ClamAV->register();
7e0e6dbe
DM
517
518# initialize all plugins
519PMG::Config::Base->init();
520
f62194b2
DM
521
522sub new {
523 my ($type) = @_;
524
525 my $class = ref($type) || $type;
526
527 my $cfg = PVE::INotify::read_file("pmg.conf");
528
529 return bless $cfg, $class;
530}
531
062f0498
DM
532# set section values
533# this does not work for ldap entries
534sub set {
535 my ($self, $section, $key, $value) = @_;
536
537 my $pdata = PMG::Config::Base->private();
538
539 die "internal error" if $section eq 'ldap';
540
541 my $plugin = $pdata->{plugins}->{$section};
542 die "no such section '$section'" if !$plugin;
543
544 my $configid = "section_$section";
545 if (defined($value)) {
546 my $tmp = PMG::Config::Base->check_value($section, $key, $value, $section, 0);
547 print Dumper($self->{ids});
548 $self->{ids}->{$configid} = { type => $section } if !defined($self->{ids}->{$configid});
549 $self->{ids}->{$configid}->{$key} = PMG::Config::Base->decode_value($section, $key, $tmp);
550 } else {
551 if (defined($self->{ids}->{$configid})) {
552 delete $self->{ids}->{$configid}->{$key};
553 }
554 }
555
556 return undef;
557}
558
f62194b2
DM
559# get section value or default
560# this does not work for ldap entries
561sub get {
562 my ($self, $section, $key) = @_;
563
564 my $pdata = PMG::Config::Base->private();
565 return undef if !defined($pdata->{options}->{$section});
566 return undef if !defined($pdata->{options}->{$section}->{$key});
567 my $pdesc = $pdata->{propertyList}->{$key};
568 return undef if !defined($pdesc);
569
570 my $configid = "section_$section";
571 if (defined($self->{ids}->{$configid}) &&
572 defined(my $value = $self->{ids}->{$configid}->{$key})) {
573 return $value;
1ccc8e95 574 }
f62194b2
DM
575
576 return $pdesc->{default};
577}
578
1ccc8e95
DM
579# get a whole section with default value
580# this does not work for ldap entries
581sub get_section {
582 my ($self, $section) = @_;
583
584 my $pdata = PMG::Config::Base->private();
585 return undef if !defined($pdata->{options}->{$section});
586
587 my $res = {};
588
589 foreach my $key (keys %{$pdata->{options}->{$section}}) {
590
591 my $pdesc = $pdata->{propertyList}->{$key};
592
593 my $configid = "section_$section";
594 if (defined($self->{ids}->{$configid}) &&
595 defined(my $value = $self->{ids}->{$configid}->{$key})) {
596 $res->{$key} = $value;
597 next;
598 }
599 $res->{$key} = $pdesc->{default};
600 }
601
602 return $res;
603}
604
be16be07
DM
605# get a whole config with default values
606# this does not work for ldap entries
607sub get_config {
608 my ($self) = @_;
609
9dab5fe5
DM
610 my $pdata = PMG::Config::Base->private();
611
be16be07
DM
612 my $res = {};
613
9dab5fe5
DM
614 foreach my $type (keys %{$pdata->{plugins}}) {
615 next if $type eq 'ldap';
616 my $plugin = $pdata->{plugins}->{$type};
617 $res->{$type} = $self->get_section($type);
be16be07
DM
618 }
619
620 return $res;
621}
622
7e0e6dbe
DM
623sub read_pmg_conf {
624 my ($filename, $fh) = @_;
f62194b2 625
7e0e6dbe 626 local $/ = undef; # slurp mode
f62194b2 627
7e0e6dbe
DM
628 my $raw = <$fh>;
629
630 return PMG::Config::Base->parse_config($filename, $raw);
631}
632
633sub write_pmg_conf {
634 my ($filename, $fh, $cfg) = @_;
635
636 my $raw = PMG::Config::Base->write_config($filename, $cfg);
637
638 PVE::Tools::safe_print($filename, $fh, $raw);
639}
640
f62194b2
DM
641PVE::INotify::register_file('pmg.conf', "/etc/proxmox/pmg.conf",
642 \&read_pmg_conf,
7e0e6dbe
DM
643 \&write_pmg_conf);
644
f609bf7f
DM
645# parsers/writers for other files
646
647my $domainsfilename = "/etc/proxmox/domains";
648
649sub read_pmg_domains {
650 my ($filename, $fh) = @_;
651
652 my $domains = [];
653
654 if (defined($fh)) {
655 while (defined(my $line = <$fh>)) {
656 if ($line =~ m/^\s*(\S+)\s*$/) {
657 my $domain = $1;
658 push @$domains, $domain;
659 }
660 }
661 }
662
663 return $domains;
664}
665
666sub write_pmg_domains {
667 my ($filename, $fh, $domain) = @_;
668
669 foreach my $domain (sort @$domain) {
670 PVE::Tools::safe_print($filename, $fh, "$domain\n");
671 }
672}
673
674PVE::INotify::register_file('domains', $domainsfilename,
675 \&read_pmg_domains,
676 \&write_pmg_domains,
677 undef, always_call_parser => 1);
678
3546daf0
DM
679my $transport_map_filename = "/etc/postfix/transport";
680
681sub read_transport_map {
682 my ($filename, $fh) = @_;
683
684 return [] if !defined($fh);
685
686 my $res = {};
687
688 while (defined(my $line = <$fh>)) {
689 chomp $line;
690 next if $line =~ m/^\s*$/;
691 next if $line =~ m/^\s*\#/;
692
693 if ($line =~ m/^(\S+)\s+smtp:([^\s:]+):(\d+)\s*$/) {
694 my $domain = $1;
695 my $host = $2;
696 my $port =$3;
697 my $nomx;
698
699 if ($host =~ m/^\[(.*)\]$/) {
700 $host = $1;
701 $nomx = 1;
702 }
703
704 my $key = "$host:$port";
705
706 $res->{$key}->{nomx} = $nomx;
707 $res->{$key}->{host} = $host;
708 $res->{$key}->{port} = $port;
709 $res->{$key}->{transport} = $key;
710
711 push @{$res->{$key}->{domains}}, $domain;
712 }
713 }
714
715 my $ta = [];
716
717 foreach my $t (sort keys %$res) {
718 push @$ta, $res->{$t};
719 }
720
721 return $ta;
722}
723
724sub write_ransport_map {
725 my ($filename, $fh, $tmap) = @_;
726
727 return if !$tmap;
728
729 foreach my $t (sort { $a->{transport} cmp $b->{transport} } @$tmap) {
730 my $domains = $t->{domains};
731
732 foreach my $d (sort @$domains) {
733 if ($t->{nomx}) {
734 PVE::Tools::safe_print($filename, $fh, "$d smtp:[$t->{host}]:$t->{port}\n");
735 } else {
736 PVE::Tools::safe_print($filename, $fh, "$d smtp:$t->{host}:$t->{port}\n");
737 }
738 }
739 }
740}
741
742PVE::INotify::register_file('transport', $transport_map_filename,
743 \&read_transport_map,
744 \&write_ransport_map,
745 undef, always_call_parser => 1);
7e0e6dbe 746
4ccdc564
DM
747# config file generation using templates
748
749sub rewrite_config_file {
750 my ($self, $tmplname, $dstfn) = @_;
751
752 my $demo = $self->get('admin', 'demo');
753
754 my $srcfn = ($tmplname =~ m|^.?/|) ?
755 $tmplname : "/var/lib/pmg/templates/$tmplname";
756
757 if ($demo) {
758 my $demosrc = "$srcfn.demo";
759 $srcfn = $demosrc if -f $demosrc;
760 }
761
762 my $srcfd = IO::File->new ($srcfn, "r")
763 || die "cant read template '$srcfn' - $!: ERROR";
764 my $dstfd = PMG::AtomicFile->open ($dstfn, "w")
765 || die "cant open config file '$dstfn' - $!: ERROR";
766
767 if ($dstfn eq '/etc/fetchmailrc') {
768 my ($login, $pass, $uid, $gid) = getpwnam('fetchmail');
769 if ($uid && $gid) {
770 chown($uid, $gid, ${*$dstfd}{'io_atomicfile_temp'});
771 }
772 chmod (0600, ${*$dstfd}{'io_atomicfile_temp'});
773 } elsif ($dstfn eq '/etc/clamav/freshclam.conf') {
774 # needed if file contains a HTTPProxyPasswort
775
776 my $uid = getpwnam('clamav');
777 my $gid = getgrnam('adm');
778
779 if ($uid && $gid) {
780 chown ($uid, $gid, ${*$dstfd}{'io_atomicfile_temp'});
781 }
782 chmod (0600, ${*$dstfd}{'io_atomicfile_temp'});
783 }
784
785 my $template = Template->new({});
786
787 my $vars = { pmg => $self->get_config() };
788
f609bf7f
DM
789 my $nodename = PVE::INotify::nodename();
790 my $int_ip = PMG::Cluster::remote_node_ip($nodename);
791 my $int_net_cidr = PMG::Utils::find_local_network_for_ip($int_ip);
792
793 $vars->{ipconfig}->{int_ip} = $int_ip;
794 # $vars->{ipconfig}->{int_net_cidr} = $int_net_cidr;
795 $vars->{ipconfig}->{int_port} = 26;
796 $vars->{ipconfig}->{ext_port} = 25;
797
798 my $transportnets = []; # fixme
799 $vars->{postfix}->{transportnets} = join(' ', @$transportnets);
800
801 my $mynetworks = [ '127.0.0.0/8', '[::1]/128' ];
802 push @$mynetworks, @$transportnets;
803 push @$mynetworks, $int_net_cidr;
804
805 # add default relay to mynetworks
806 if (my $relay = $self->get('mail', 'relay')) {
807 if (Net::IP::ip_is_ipv4($relay)) {
808 push @$mynetworks, "$relay/32";
809 } elsif (Net::IP::ip_is_ipv6($relay)) {
810 push @$mynetworks, "[$relay]/128";
811 } else {
812 warn "unable to detect IP version of relay '$relay'";
813 }
814 }
815
816 $vars->{postfix}->{mynetworks} = join(' ', @$mynetworks);
817
818 my $usepolicy = 0;
819 $usepolicy = 1 if $self->get('mail', 'greylist') ||
820 $self->get('mail', 'spf') || $self->get('mail', 'use_rbl');
821 $vars->{postfix}->{usepolicy} = $usepolicy;
822
823 my $resolv = PVE::INotify::read_file('resolvconf');
824 $vars->{dns}->{hostname} = $nodename;
825 $vars->{dns}->{domain} = $resolv->{search};
826
4ccdc564
DM
827 $template->process($srcfd, $vars, $dstfd) ||
828 die $template->error();
829
830 $srcfd->close();
831 $dstfd->close (1);
832}
833
834sub rewrite_config_script {
835 my ($self, $tmplname, $dstfn) = @_;
836
837 $self->rewrite_config_file($tmplname, $dstfn);
838 system("chmod +x $dstfn");
839}
840
9123cab5
DM
841# rewrite spam configuration
842sub rewrite_config_spam {
843 my ($self) = @_;
844
845 my $use_awl = $self->get('spam', 'use_awl');
846 my $use_bayes = $self->get('spam', 'use_bayes');
847 my $use_razor = $self->get('spam', 'use_razor');
848
849 # delete AW and bayes databases if those features are disabled
850 unlink '/root/.spamassassin/auto-whitelist' if !$use_awl;
851 if (!$use_bayes) {
852 unlink '/root/.spamassassin/bayes_journal';
853 unlink '/root/.spamassassin/bayes_seen';
854 unlink '/root/.spamassassin/bayes_toks';
855 }
856
857 # make sure we have a custom.cf file (else cluster sync fails)
858 IO::File->new('/etc/mail/spamassassin/custom.cf', 'a', 0644);
859
4ccdc564
DM
860 $self->rewrite_config_file('local.cf.in', '/etc/mail/spamassassin/local.cf');
861 $self->rewrite_config_file('init.pre.in', '/etc/mail/spamassassin/init.pre');
862 $self->rewrite_config_file('v310.pre.in', '/etc/mail/spamassassin/v310.pre');
863 $self->rewrite_config_file('v320.pre.in', '/etc/mail/spamassassin/v320.pre');
9123cab5
DM
864
865 if ($use_razor) {
866 mkdir "/root/.razor";
4ccdc564 867 $self->rewrite_config_file('razor-agent.conf.in', '/root/.razor/razor-agent.conf');
9123cab5
DM
868 if (! -e '/root/.razor/identity') {
869 eval {
870 my $timeout = 30;
871 PVE::Tools::run_command (['razor-admin', '-discover'], timeout => $timeout);
872 PVE::Tools::run_command (['razor-admin', '-register'], timeout => $timeout);
873 };
874 my $err = $@;
875 syslog('info', msgquote ("registering razor failed: $err")) if $err;
876 }
877 }
878}
879
ac5d1312
DM
880# rewrite ClamAV configuration
881sub rewrite_config_clam {
882 my ($self) = @_;
883
4ccdc564
DM
884 $self->rewrite_config_file('clamd.conf.in', '/etc/clamav/clamd.conf');
885 $self->rewrite_config_file('freshclam.conf.in', '/etc/clamav/freshclam.conf');
ac5d1312
DM
886}
887
86737f12
DM
888sub rewrite_config_postgres {
889 my ($self) = @_;
890
891 my $pgconfdir = "/etc/postgresql/9.6/main";
892
893 $self->rewrite_config_file('pg_hba.conf.in', "$pgconfdir/pg_hba.conf");
894 $self->rewrite_config_file('postgresql.conf.in', "$pgconfdir/postgresql.conf");
895}
896
897# rewrite /root/.forward
898sub rewrite_dot_forward {
899 my ($self) = @_;
900
901 my $fname = '/root/.forward';
902
903 my $email = $self->get('administration', 'email');
904 open(TMP, ">$fname");
905 if ($email && $email =~ m/\s*(\S+)\s*/) {
906 print (TMP "$1\n");
907 } else {
908 # empty .forward does not forward mails (see man local)
909 }
910 close (TMP);
911}
912
f609bf7f
DM
913# rewrite /etc/postfix/*
914sub rewrite_config_postfix {
915 my ($self) = @_;
916
3546daf0 917 # make sure we have required files (else postfix start fails)
f609bf7f 918 IO::File->new($domainsfilename, 'a', 0644);
3546daf0 919 IO::File->new($transport_map_filename, 'a', 0644);
f609bf7f
DM
920
921 if ($self->get('mail', 'tls')) {
922 eval {
923 my $resolv = PVE::INotify::read_file('resolvconf');
924 my $domain = $resolv->{search};
925
926 my $company = $domain; # what else ?
927 my $cn = "*.$domain";
928 PMG::Utils::gen_proxmox_tls_cert(0, $company, $cn);
929 };
930 syslog ('info', msgquote ("generating certificate failed: $@")) if $@;
931 }
932
933 $self->rewrite_config_file('main.cf.in', '/etc/postfix/main.cf');
934 $self->rewrite_config_file('master.cf.in', '/etc/postfix/master.cf');
935 #rewrite_config_transports ($class);
936 #rewrite_config_whitelist ($class);
937 #rewrite_config_tls_policy ($class);
938
939 # make sure aliases.db is up to date
940 system('/usr/bin/newaliases');
941}
942
f983300f
DM
943sub rewrite_config {
944 my ($self) = @_;
945
f609bf7f 946 $self->rewrite_config_postfix();
86737f12
DM
947 $self->rewrite_dot_forward();
948 $self->rewrite_config_postgres();
f983300f
DM
949 $self->rewrite_config_spam();
950 $self->rewrite_config_clam();
f609bf7f 951
f983300f
DM
952}
953
7e0e6dbe 9541;