]> git.proxmox.com Git - pmg-api.git/blobdiff - PMG/Utils.pm
fix bug #1625 - change default rule priorities
[pmg-api.git] / PMG / Utils.pm
index fdfefc456e875254601e7db49462bda7ad8c6d00..aa0da54965d7a32675621fe5f39e49271bf9f362 100644 (file)
@@ -17,6 +17,7 @@ use Time::Local;
 use Xdgmime;
 use Data::Dumper;
 use Digest::SHA;
+use Digest::MD5;
 use Net::IP;
 use Socket;
 use RRDs;
@@ -33,22 +34,12 @@ use PMG::AtomicFile;
 use PMG::MailQueue;
 use PMG::SMTPPrinter;
 
-my $realm_regex = qr/[A-Za-z][A-Za-z0-9\.\-_]+/;
-
-PVE::JSONSchema::register_format('pmg-realm', \&verify_realm);
-sub verify_realm {
-    my ($realm, $noerr) = @_;
-
-    if ($realm !~ m/^${realm_regex}$/) {
-       return undef if $noerr;
-       die "value does not look like a valid realm\n";
-    }
-    return $realm;
-}
+my $valid_pmg_realms = ['pam', 'pmg', 'quarantine'];
 
 PVE::JSONSchema::register_standard_option('realm', {
     description => "Authentication domain ID",
-    type => 'string', format => 'pmg-realm',
+    type => 'string',
+    enum => $valid_pmg_realms,
     maxLength => 32,
 });
 
@@ -86,7 +77,8 @@ sub verify_username {
     # colon separated lists)!
     # slash is not allowed because it is used as pve API delimiter
     # also see "man useradd"
-    if ($username =~ m!^([^\s:/]+)\@(${realm_regex})$!) {
+    my $realm_list = join('|', @$valid_pmg_realms);
+    if ($username =~ m!^([^\s:/]+)\@(${realm_list})$!) {
        return wantarray ? ($username, $1, $2) : $username;
     }
 
@@ -539,6 +531,9 @@ sub get_full_service_state {
     return $res;
 }
 
+our $db_service_list = [
+    'pmgpolicy', 'pmgmirror', 'pmgtunnel', 'pmg-smtp-filter' ];
+
 sub service_wait_stopped {
     my ($timeout, $service_list) = @_;
 
@@ -575,14 +570,14 @@ sub service_cmd {
     my ($service, $cmd) = @_;
 
     die "unknown service command '$cmd'\n"
-       if $cmd !~ m/^(start|stop|restart|reload)$/;
+       if $cmd !~ m/^(start|stop|restart|reload|reload-or-restart)$/;
 
     if ($service eq 'pmgdaemon' || $service eq 'pmgproxy') {
-       if ($cmd eq 'restart') {
-           # OK
-       } else {
-           die "invalid service cmd '$service $cmd': ERROR";
-       }
+       die "invalid service cmd '$service $cmd': ERROR" if $cmd eq 'stop';
+    } elsif ($service eq 'fetchmail') {
+       # use restart instead of start - else it does not start 'exited' unit
+       # after setting START_DAEMON=yes in /etc/default/fetchmail
+       $cmd = 'restart' if $cmd eq 'start';
     }
 
     $service = $service_aliases->{$service} // $service;
@@ -795,7 +790,7 @@ sub update_node_status_rrd {
     my $netin = 0;
     my $netout = 0;
     foreach my $dev (keys %$netdev) {
-       next if $dev !~ m/^eth\d+$/;
+       next if $dev !~ m/^$PVE::Network::PHYSICAL_NIC_RE$/;
        $netin += $netdev->{$dev}->{receive};
        $netout += $netdev->{$dev}->{transmit};
     }
@@ -971,10 +966,13 @@ sub bencode_header {
 }
 
 sub load_sa_descriptions {
+    my ($additional_dirs) = @_;
 
     my @dirs = ('/usr/share/spamassassin',
                '/usr/share/spamassassin-extra');
 
+    push @dirs, @$additional_dirs if @$additional_dirs;
+
     my $res = {};
 
     my $parse_sa_file = sub {
@@ -1002,6 +1000,8 @@ sub load_sa_descriptions {
        }
     }
 
+    $res->{'ClamAVHeuristics'}->{desc} = "ClamAV heuristic tests";
+
     return $res;
 }
 
@@ -1083,4 +1083,99 @@ sub lookup_timespan {
     return ($start, $end);
 }
 
+my $rbl_scan_last_cursor;
+my $rbl_scan_start_time = time();
+
+sub scan_journal_for_rbl_rejects {
+
+    # example postscreen log entry for RBL rejects
+    # Aug 29 08:00:36 proxmox postfix/postscreen[11266]: NOQUEUE: reject: RCPT from [x.x.x.x]:1234: 550 5.7.1 Service unavailable; client [x.x.x.x] blocked using zen.spamhaus.org; from=<xxxx>, to=<yyyy>, proto=ESMTP, helo=<zzz>
+
+    # example for PREGREET reject
+    # Dec  7 06:57:11 proxmox postfix/postscreen[32084]: PREGREET 14 after 0.23 from [x.x.x.x]:63492: EHLO yyyyy\r\n
+
+    my $identifier = 'postfix/postscreen';
+
+    my $rbl_count = 0;
+    my $pregreet_count = 0;
+
+    my $parser = sub {
+       my $line = shift;
+
+       if ($line =~ m/^--\scursor:\s(\S+)$/) {
+           $rbl_scan_last_cursor = $1;
+           return;
+       }
+
+       if ($line =~ m/\s$identifier\[\d+\]:\sNOQUEUE:\sreject:.*550 5.7.1 Service unavailable;/) {
+           $rbl_count++;
+       } elsif ($line =~ m/\s$identifier\[\d+\]:\sPREGREET\s\d+\safter\s/) {
+           $pregreet_count++;
+       }
+    };
+
+    # limit to last 5000 lines to avoid long delays
+    my $cmd = ['journalctl', '--show-cursor', '-o', 'short-unix', '--no-pager',
+              '--identifier', $identifier, '-n', 5000];
+
+    if (defined($rbl_scan_last_cursor)) {
+       push @$cmd, "--after-cursor=${rbl_scan_last_cursor}";
+    } else {
+       push @$cmd, "--since=@" . $rbl_scan_start_time;
+    }
+
+    PVE::Tools::run_command($cmd, outfunc => $parser);
+
+    return ($rbl_count, $pregreet_count);
+}
+
+my $hwaddress;
+
+sub get_hwaddress {
+
+    return $hwaddress if defined ($hwaddress);
+
+    my $fn = '/etc/ssh/ssh_host_rsa_key.pub';
+    my $sshkey = PVE::Tools::file_get_contents($fn);
+    $hwaddress = uc(Digest::MD5::md5_hex($sshkey));
+
+    return $hwaddress;
+}
+
+my $default_locale = "en_US.UTF-8 UTF-8";
+
+sub cond_add_default_locale {
+
+    my $filename = "/etc/locale.gen";
+
+    open(my $infh, "<", $filename) || return;
+
+    while (defined(my $line = <$infh>)) {
+       if ($line =~ m/^\Q${default_locale}\E/) {
+           # already configured
+           return;
+       }
+    }
+
+    seek($infh, 0, 0) // return; # seek failed
+
+    open(my $outfh, ">", "$filename.tmp") || return;
+
+    my $done;
+    while (defined(my $line = <$infh>)) {
+       if ($line =~ m/^#\s*\Q${default_locale}\E.*/) {
+           print $outfh "${default_locale}\n" if !$done;
+           $done = 1;
+       } else {
+           print $outfh $line;
+       }
+    }
+
+    print STDERR "generation pmg default locale\n";
+
+    rename("$filename.tmp", $filename) || return; # rename failed
+
+    system("dpkg-reconfigure locales -f noninteractive");
+}
+
 1;