]>
git.proxmox.com Git - pmg-api.git/blob - src/PMG/RuleCache.pm
4bde2e7cbd5bb088edba69e312fc40caae6dcf69
1 package PMG
::RuleCache
;
13 my $ocache_size = 1023;
16 my ($type, $ruledb) = @_;
20 $self->{ruledb
} = $ruledb;
27 my $dbh = $ruledb->{dbh
};
29 my $sha1 = Digest
::SHA-
>new;
42 # read a consistent snapshot
43 $dbh->do("SET TRANSACTION ISOLATION LEVEL SERIALIZABLE");
45 my $sth = $dbh->prepare(
46 "SELECT ID, Name, Priority, Active, Direction FROM Rule " .
48 "ORDER BY Priority DESC, ID DESC");
52 while (my $ref = $sth->fetchrow_hashref()) {
53 my $ruleid = $ref->{id
};
54 my $rule = PMG
::RuleDB
::Rule-
>new(
55 $ref->{name
}, $ref->{priority
}, $ref->{active
},
58 $rule->{id
} = $ruleid;
61 $sha1->add(join(',', $ref->{id
}, $ref->{name
}, $ref->{priority
}, $ref->{active
},
62 $ref->{direction
}) . "|");
64 $self->{"$ruleid:from"} = { groups
=> [] };
65 $self->{"$ruleid:to"} = { groups
=> [] };
66 $self->{"$ruleid:when"} = { groups
=> [] };
67 $self->{"$ruleid:what"} = { groups
=> [] };
68 $self->{"$ruleid:action"} = { groups
=> [] };
70 my $attribute_sth = $dbh->prepare("SELECT * FROM Rule_Attributes WHERE Rule_ID = ? ORDER BY Name");
71 $attribute_sth->execute($ruleid);
73 my $rule_attributes = [];
74 while (my $ref = $attribute_sth->fetchrow_hashref()) {
75 if ($ref->{name
} =~ m/^(from|to|when|what)-(and|invert)$/) {
78 my $value = $ref->{value
};
79 $self->{"${ruleid}:${type}"}->{$prop} = $value;
81 $sha1->add("${ruleid}:${type}-${prop}=${value}|");
85 my $sth1 = $dbh->prepare(
86 "SELECT Objectgroup_ID, Grouptype FROM RuleGroup " .
87 "where RuleGroup.Rule_ID = '$ruleid' " .
88 "ORDER BY Grouptype, Objectgroup_ID");
91 while (my $ref1 = $sth1->fetchrow_hashref()) {
92 my $gtype = $ref1->{grouptype
};
93 my $groupid = $ref1->{objectgroup_id
};
96 my $sth2 = $dbh->prepare(
97 "SELECT ID FROM Object where Objectgroup_ID = '$groupid' " .
100 while (my $ref2 = $sth2->fetchrow_hashref()) {
101 my $objid = $ref2->{'id'};
102 my $obj = $self->_get_object($objid);
104 $sha1->add (join (',', $objid, $gtype, $groupid) . "|");
105 $sha1->add ($obj->{digest
}, "|");
107 push @$objects, $obj;
109 if ($gtype == 3) { # what
110 if ($obj->otype == PMG
::RuleDB
::ArchiveFilter-
>otype ||
111 $obj->otype == PMG
::RuleDB
::MatchArchiveFilename-
>otype)
113 if ($rule->{direction
} == 0) {
114 $self->{archivefilter_in
} = 1;
115 } elsif ($rule->{direction
} == 1) {
116 $self->{archivefilter_out
} = 1;
118 $self->{archivefilter_in
} = 1;
119 $self->{archivefilter_out
} = 1;
122 } elsif ($gtype == 4) { # action
123 $self->{"$ruleid:final"} = 1 if $obj->final();
132 my $objectgroup_sth = $dbh->prepare("SELECT * FROM Objectgroup_Attributes WHERE Objectgroup_ID = ?");
133 $objectgroup_sth->execute($groupid);
135 while (my $ref = $objectgroup_sth->fetchrow_hashref()) {
136 $group->{and} = $ref->{value
} if $ref->{name
} eq 'and';
137 $group->{invert
} = $ref->{value
} if $ref->{name
} eq 'invert';
139 $sha1->add (join(',', $groupid, $group->{and} // 0, $group->{invert
} // 0), "|");
141 my $type = $type_map->{$gtype};
142 push $self->{"$ruleid:$type"}->{groups
}->@*, $group;
148 # Cache Greylist Exclusion
149 $sth = $dbh->prepare(
150 "SELECT object.id FROM object, objectgroup " .
151 "WHERE class = 'greylist' AND " .
152 "objectgroup.id = object.objectgroup_id " .
153 "ORDER BY object.id");
156 my $grey_excl_sender = ();
157 my $grey_excl_receiver = ();
158 while (my $ref2 = $sth->fetchrow_hashref()) {
159 my $obj = $self->_get_object ($ref2->{'id'});
161 if ($obj->receivertest()) {
162 push @$grey_excl_receiver, $obj;
164 push @$grey_excl_sender, $obj;
166 $sha1->add ($ref2->{'id'}, "|");
167 $sha1->add ($obj->{digest
}, "|");
170 $self->{"greylist:sender"} = $grey_excl_sender;
171 $self->{"greylist:receiver"} = $grey_excl_receiver;
177 $dbh->rollback; # end transaction
179 syslog
('err', "unable to load rulecache : $err") if $err;
181 $self->{rules
} = $rules;
183 $self->{digest
} = $sha1->hexdigest;
189 my ($self, $ruleid) = @_;
191 defined($ruleid) || die "undefined rule id: ERROR";
193 return $self->{"$ruleid:final"};
203 my ($self, $objid) = @_;
205 my $cid = $objid % $ocache_size;
207 my $obj = $self->{ocache
}[$cid];
209 if (!defined ($obj) || $obj->{id
} != $objid) {
210 $obj = $self->{ruledb
}->load_object($objid);
211 $self->{ocache
}[$cid] = $obj;
214 $obj || die "unable to get object $objid: ERROR";
220 my ($self, $ruleid) = @_;
222 defined($ruleid) || die "undefined rule id: ERROR";
224 my $actions = $self->{"$ruleid:action"};
226 return undef if scalar($actions->{groups
}->@*) == 0;
229 for my $action ($actions->{groups
}->@*) {
230 push $res->@*, $action->{objects
}->@*;
236 my ($self, $addr, $ip) = @_;
238 my $grey = $self->{"greylist:sender"};
240 foreach my $obj (@$grey) {
241 if ($obj->who_match ($addr, $ip)) {
249 sub greylist_match_receiver
{
250 my ($self, $addr) = @_;
252 my $grey = $self->{"greylist:receiver"};
254 foreach my $obj (@$grey) {
255 if ($obj->who_match($addr)) {
264 my ($self, $ruleid, $addr, $ip, $ldap) = @_;
266 my $from = $self->{"$ruleid:from"};
268 return 1 if scalar($from->{groups
}->@*) == 0;
270 # postfix prefixes ipv6 addresses with IPv6:
271 if (defined($ip) && $ip =~ /^IPv6:(.*)/) {
275 for my $group ($from->{groups
}->@*) {
276 for my $obj ($group->{objects
}->@*) {
277 return 1 if $obj->who_match($addr, $ip, $ldap);
285 my ($self, $ruleid, $addr, $ldap) = @_;
287 my $to = $self->{"$ruleid:to"};
289 return 1 if scalar($to->{groups
}->@*) == 0;
291 for my $group ($to->{groups
}->@*) {
292 for my $obj ($group->{objects
}->@*) {
293 return 1 if $obj->who_match($addr, undef, $ldap);
302 my ($self, $ruleid, $time) = @_;
304 my $when = $self->{"$ruleid:when"};
306 return 1 if scalar($when->{groups
}->@*) == 0;
308 for my $group ($when->{groups
}->@*) {
309 for my $obj ($group->{objects
}->@*) {
310 return 1 if $obj->when_match($time);
318 my ($self, $ruleid, $queue, $element, $msginfo, $dbh) = @_;
320 my $what = $self->{"$ruleid:what"};
325 if (scalar($what->{groups
}->@*) == 0) {
327 foreach my $target (@{$msginfo->{targets
}}) {
328 $marks->{$target} = [];
330 return ($marks, $spaminfo);
333 for my $group ($what->{groups
}->@*) {
334 for my $obj ($group->{objects
}->@*) {
335 if (!$obj->can('what_match_targets')) {
336 if (my $match = $obj->what_match($queue, $element, $msginfo, $dbh)) {
337 for my $target ($msginfo->{targets
}->@*) {
338 push $marks->{$target}->@*, $match->@*;
342 if (my $target_info = $obj->what_match_targets($queue, $element, $msginfo, $dbh)) {
343 foreach my $k (keys $target_info->%*) {
344 push $marks->{$k}->@*, $target_info->{$k}->{marks
}->@*;
345 # only save spaminfo once
346 $spaminfo = $target_info->{$k}->{spaminfo
} if !defined($spaminfo);
353 return ($marks, $spaminfo);