From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 8841892485 for ; Thu, 1 Feb 2024 16:37:29 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 6B68812D0C for ; Thu, 1 Feb 2024 16:36:59 +0100 (CET) Received: from proxmox-new.maurer-it.com (proxmox-new.maurer-it.com [94.136.29.106]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Thu, 1 Feb 2024 16:36:58 +0100 (CET) Received: from proxmox-new.maurer-it.com (localhost.localdomain [127.0.0.1]) by proxmox-new.maurer-it.com (Proxmox) with ESMTP id 5B3C941FBC for ; Thu, 1 Feb 2024 16:36:58 +0100 (CET) From: Dominik Csapak To: pmg-devel@lists.proxmox.com Date: Thu, 1 Feb 2024 16:36:48 +0100 Message-Id: <20240201153657.1067215-3-d.csapak@proxmox.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20240201153657.1067215-1-d.csapak@proxmox.com> References: <20240201153657.1067215-1-d.csapak@proxmox.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL 0.020 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_PASS -0.001 SPF: sender matches SPF record T_SCC_BODY_TEXT_LINE -0.01 - Subject: [pmg-devel] [RFC PATCH pmg-api 02/11] RuleCache: reorganize to keep group structure X-BeenThere: pmg-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox Mail Gateway development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 01 Feb 2024 15:37:29 -0000 Currently we 'or' combine all objects of a type (from/to/what/when) regardless of group, so we only keep a single list of all objects. Since we want to introduce different logic (and/invert) we want to keep the configured group structure. This patch does this, wihtout chaning the current matching logic (still all 'or'-ed). Signed-off-by: Dominik Csapak --- src/PMG/RuleCache.pm | 115 ++++++++++++++++++++++++------------------- 1 file changed, 64 insertions(+), 51 deletions(-) diff --git a/src/PMG/RuleCache.pm b/src/PMG/RuleCache.pm index 51d8a07..fd22a16 100644 --- a/src/PMG/RuleCache.pm +++ b/src/PMG/RuleCache.pm @@ -28,6 +28,14 @@ sub new { my $sha1 = Digest::SHA->new; + my $type_map = { + 0 => "from", + 1 => "to", + 2 => "when", + 3 => "what", + 4 => "action", + }; + eval { $dbh->begin_work; @@ -53,7 +61,11 @@ sub new { $sha1->add(join(',', $ref->{id}, $ref->{name}, $ref->{priority}, $ref->{active}, $ref->{direction}) . "|"); - my ($from, $to, $when, $what, $action); + $self->{"$ruleid:from"} = { groups => [] }; + $self->{"$ruleid:to"} = { groups => [] }; + $self->{"$ruleid:when"} = { groups => [] }; + $self->{"$ruleid:what"} = { groups => [] }; + $self->{"$ruleid:action"} = { groups => [] }; my $sth1 = $dbh->prepare( "SELECT Objectgroup_ID, Grouptype FROM RuleGroup " . @@ -64,20 +76,7 @@ sub new { while (my $ref1 = $sth1->fetchrow_hashref()) { my $gtype = $ref1->{grouptype}; my $groupid = $ref1->{objectgroup_id}; - - # emtyp groups differ from non-existent groups! - - if ($gtype == 0) { #from - $from = [] if !defined ($from); - } elsif ($gtype == 1) { # to - $to = [] if !defined ($to); - } elsif ($gtype == 2) { # when - $when = [] if !defined ($when); - } elsif ($gtype == 3) { # what - $what = [] if !defined ($what); - } elsif ($gtype == 4) { # action - $action = [] if !defined ($action); - } + my $objects = []; my $sth2 = $dbh->prepare( "SELECT ID FROM Object where Objectgroup_ID = '$groupid' " . @@ -90,14 +89,9 @@ sub new { $sha1->add (join (',', $objid, $gtype, $groupid) . "|"); $sha1->add ($obj->{digest}, "|"); - if ($gtype == 0) { #from - push @$from, $obj; - } elsif ($gtype == 1) { # to - push @$to, $obj; - } elsif ($gtype == 2) { # when - push @$when, $obj; - } elsif ($gtype == 3) { # what - push @$what, $obj; + push @$objects, $obj; + + if ($gtype == 3) { # what if ($obj->otype == PMG::RuleDB::ArchiveFilter->otype || $obj->otype == PMG::RuleDB::MatchArchiveFilename->otype) { @@ -111,20 +105,20 @@ sub new { } } } elsif ($gtype == 4) { # action - push @$action, $obj; $self->{"$ruleid:final"} = 1 if $obj->final(); } } $sth2->finish(); + + my $group = { + objects => $objects, + }; + + my $type = $type_map->{$gtype}; + push $self->{"$ruleid:$type"}->{groups}->@*, $group; } $sth1->finish(); - - $self->{"$ruleid:from"} = $from; - $self->{"$ruleid:to"} = $to; - $self->{"$ruleid:when"} = $when; - $self->{"$ruleid:what"} = $what; - $self->{"$ruleid:action"} = $action; } # Cache Greylist Exclusion @@ -203,7 +197,15 @@ sub get_actions { defined($ruleid) || die "undefined rule id: ERROR"; - return $self->{"$ruleid:action"}; + my $actions = $self->{"$ruleid:action"}; + + return undef if scalar($actions->{groups}->@*) == 0; + + my $res = []; + for my $action ($actions->{groups}->@*) { + push $res->@*, $action->{objects}->@*; + } + return $res; } sub greylist_match { @@ -239,15 +241,17 @@ sub from_match { my $from = $self->{"$ruleid:from"}; - return 1 if !defined ($from); + return 1 if scalar($from->{groups}->@*) == 0; # postfix prefixes ipv6 addresses with IPv6: if (defined($ip) && $ip =~ /^IPv6:(.*)/) { $ip = $1; } - foreach my $obj (@$from) { - return 1 if $obj->who_match($addr, $ip, $ldap); + for my $group ($from->{groups}->@*) { + for my $obj ($group->{objects}->@*) { + return 1 if $obj->who_match($addr, $ip, $ldap); + } } return 0; @@ -258,12 +262,15 @@ sub to_match { my $to = $self->{"$ruleid:to"}; - return 1 if !defined ($to); + return 1 if scalar($to->{groups}->@*) == 0; - foreach my $obj (@$to) { - return 1 if $obj->who_match($addr, undef, $ldap); + for my $group ($to->{groups}->@*) { + for my $obj ($group->{objects}->@*) { + return 1 if $obj->who_match($addr, undef, $ldap); + } } + return 0; } @@ -272,10 +279,12 @@ sub when_match { my $when = $self->{"$ruleid:when"}; - return 1 if !defined ($when); + return 1 if scalar($when->{groups}->@*) == 0; - foreach my $obj (@$when) { - return 1 if $obj->when_match($time); + for my $group ($when->{groups}->@*) { + for my $obj ($group->{objects}->@*) { + return 1 if $obj->when_match($time); + } } return 0; @@ -292,7 +301,7 @@ sub what_match { # $res->{$target}->{marks} is only used in apply_rules() to exclude some # targets (spam blacklist and whitelist) - if (!defined ($what)) { + if (scalar($what->{groups}->@*) == 0) { # match all targets foreach my $target (@{$msginfo->{targets}}) { $res->{$target}->{marks} = []; @@ -304,10 +313,12 @@ sub what_match { my $marks; - foreach my $obj (@$what) { - if (!$obj->can('what_match_targets')) { - if (my $match = $obj->what_match($queue, $element, $msginfo, $dbh)) { - push @$marks, @$match; + for my $group ($what->{groups}->@*) { + for my $obj ($group->{objects}->@*) { + if (!$obj->can('what_match_targets')) { + if (my $match = $obj->what_match($queue, $element, $msginfo, $dbh)) { + push @$marks, @$match; + } } } } @@ -317,12 +328,14 @@ sub what_match { $res->{marks} = $marks; } - foreach my $obj (@$what) { - if ($obj->can ("what_match_targets")) { - my $target_info; - if ($target_info = $obj->what_match_targets($queue, $element, $msginfo, $dbh)) { - foreach my $k (keys %$target_info) { - $res->{$k} = $target_info->{$k}; + for my $group ($what->{groups}->@*) { + for my $obj ($group->{objects}->@*) { + if ($obj->can ("what_match_targets")) { + my $target_info; + if ($target_info = $obj->what_match_targets($queue, $element, $msginfo, $dbh)) { + foreach my $k (keys %$target_info) { + $res->{$k} = $target_info->{$k}; + } } } } -- 2.30.2