14 use PMG
::RuleDB
::Group
;
16 #use Proxmox::Statistic;
17 use PMG
::RuleDB
::Object
;
18 use PMG
::RuleDB
::WhoRegex
;
19 use PMG
::RuleDB
::ReceiverRegex
;
20 use PMG
::RuleDB
::EMail
;
21 use PMG
::RuleDB
::Receiver
;
22 use PMG
::RuleDB
::IPAddress
;
23 use PMG
::RuleDB
::IPNet
;
24 use PMG
::RuleDB
::Domain
;
25 use PMG
::RuleDB
::ReceiverDomain
;
27 #use Proxmox::RuleDB::LDAP;
28 #use Proxmox::RuleDB::LDAPUser;
29 use PMG
::RuleDB
::TimeFrame
;
30 use PMG
::RuleDB
::Spam
;
31 use PMG
::RuleDB
::ReportSpam
;
32 use PMG
::RuleDB
::Virus
;
33 use PMG
::RuleDB
::Accept
;
34 use PMG
::RuleDB
::Remove
;
35 use PMG
::RuleDB
::ModField
;
36 use PMG
::RuleDB
::MatchField
;
37 use PMG
::RuleDB
::MatchFilename
;
38 use PMG
::RuleDB
::Attach
;
39 use PMG
::RuleDB
::Disclaimer
;
41 use PMG
::RuleDB
::Quarantine
;
42 use PMG
::RuleDB
::Block
;
43 use PMG
::RuleDB
::Counter
;
44 use PMG
::RuleDB
::Notify
;
45 use PMG
::RuleDB
::Rule
;
46 use PMG
::RuleDB
::ContentTypeFilter
;
47 use PMG
::RuleDB
::ArchiveFilter
;
50 my ($type, $dbh) = @_;
52 $dbh = PMG
::DBTools
::open_ruledb
("Proxmox_ruledb") if !defined ($dbh);
54 my $self = bless { dbh
=> $dbh }, $type;
62 $self->{dbh
}->disconnect();
65 sub create_group_with_obj
{
66 my ($self, $obj, $name, $info) = @_;
71 defined($obj) || die "proxmox: undefined object";
78 $self->{dbh
}->begin_work;
80 $self->{dbh
}->do("INSERT INTO Objectgroup (Name, Info, Class) " .
81 "VALUES (?, ?, ?)", undef,
82 $name, $info, $obj->oclass());
84 my $lid = PMG
::Utils
::lastid
($self->{dbh
}, 'objectgroup_id_seq');
86 $og = PMG
::RuleDB
::Group-
>new($name, $info, $obj->oclass());
89 $obj->{ogroup
} = $lid;
90 $id = $obj->save($self, 1);
91 $obj->{id
} = $id; # just to be sure
96 $self->{dbh
}->rollback;
103 my ($self, $rule) = @_;
105 defined($rule->{id
}) || die "undefined rule id: ERROR";
107 my $sth = $self->{dbh
}->prepare(
108 "SELECT RuleGroup.Grouptype, Objectgroup.ID, " .
109 "Objectgroup.Name, Objectgroup.Info " .
110 "FROM Rulegroup, Objectgroup " .
111 "WHERE Rulegroup.Rule_ID = ? and " .
112 "Rulegroup.Objectgroup_ID = Objectgroup.ID " .
113 "ORDER BY RuleGroup.Grouptype");
117 $sth->execute($rule->{id
});
119 my ($from, $to, $when, $what, $action) = ((), (), (), (), ());
121 while (my $ref = $sth->fetchrow_hashref()) {
122 my $og = PMG
::RuleDB
::Group-
>new($ref->{name
}, $ref->{info
});
123 $og->{id
} = $ref->{id
};
125 if ($ref->{'grouptype'} == 0) { #from
127 } elsif ($ref->{'grouptype'} == 1) { # to
129 } elsif ($ref->{'grouptype'} == 2) { # when
131 } elsif ($ref->{'grouptype'} == 3) { # what
133 } elsif ($ref->{'grouptype'} == 4) { # action
134 my $objects = $self->load_group_objects($og->{id
});
135 my $obj = @$objects[0];
136 defined($obj) || die "undefined action object: ERROR";
137 $og->{action
} = $obj;
144 return ($from, $to, $when, $what, $action);
148 my ($self, $og) = @_;
150 defined($og->{name
}) ||
151 die "undefined group attribute - name: ERROR";
152 defined($og->{info
}) ||
153 die "undefined group attribute - info: ERROR";
154 defined($og->{class}) ||
155 die "undefined group attribute - class: ERROR";
157 if (defined($og->{id
})) {
159 $self->{dbh
}->do("UPDATE Objectgroup " .
160 "SET Name = ?, Info = ? " .
161 "WHERE ID = ?", undef,
162 $og->{name
}, $og->{info
}, $og->{id
});
167 my $sth = $self->{dbh
}->prepare(
168 "INSERT INTO Objectgroup (Name, Info, Class) " .
169 "VALUES (?, ?, ?);");
171 $sth->execute($og->name, $og->info, $og->class);
173 return $og->{id
} = PMG
::Utils
::lastid
($self->{dbh
}, 'objectgroup_id_seq');
180 my ($self, $groupid) = @_;
182 defined($groupid) || die "undefined group id: ERROR";
186 $self->{dbh
}->begin_work;
188 # test if group is used in rules
189 $self->{dbh
}->do("LOCK TABLE RuleGroup IN EXCLUSIVE MODE");
191 my $sth = $self->{dbh
}->prepare(
192 "SELECT Rule.Name as rulename, ObjectGroup.Name as groupname " .
193 "FROM RuleGroup, Rule, ObjectGroup WHERE " .
194 "ObjectGroup.ID = ? AND Objectgroup_ID = ObjectGroup.ID AND " .
195 "Rule_ID = Rule.ID");
197 $sth->execute($groupid);
199 if (my $ref = $sth->fetchrow_hashref()) {
200 die "Group '$ref->{groupname}' is used by rule '$ref->{rulename}' - unable to delete\n";
205 $self->{dbh
}->do("DELETE FROM ObjectGroup " .
206 "WHERE ID = ?", undef, $groupid);
208 $self->{dbh
}->do("DELETE FROM RuleGroup " .
209 "WHERE Objectgroup_ID = ?", undef, $groupid);
211 $sth = $self->{dbh
}->prepare("SELECT * FROM Object " .
212 "where Objectgroup_ID = ?");
213 $sth->execute($groupid);
215 while (my $ref = $sth->fetchrow_hashref()) {
216 $self->{dbh
}->do("DELETE FROM Attribut " .
217 "WHERE Object_ID = ?", undef, $ref->{id
});
222 $self->{dbh
}->do("DELETE FROM Object " .
223 "WHERE Objectgroup_ID = ?", undef, $groupid);
225 $self->{dbh
}->commit;
228 $self->{dbh
}->rollback;
235 sub load_objectgroups
{
236 my ($self, $class, $id) = @_;
240 defined($class) || die "undefined object class";
242 if (!(defined($id))) {
243 $sth = $self->{dbh
}->prepare(
244 "SELECT * FROM Objectgroup where Class = ? ORDER BY name");
245 $sth->execute($class);
248 $sth = $self->{dbh
}->prepare(
249 "SELECT * FROM Objectgroup where Class like ? and id = ? " .
251 $sth->execute($class,$id);
255 while (my $ref = $sth->fetchrow_hashref()) {
256 my $og = PMG
::RuleDB
::Group-
>new($ref->{name
}, $ref->{info
},
258 $og->{id
} = $ref->{id
};
260 if ($class eq 'action') {
261 my $objects = $self->load_group_objects($og->{id
});
262 my $obj = @$objects[0];
263 defined($obj) || die "undefined action object: ERROR";
264 $og->{action
} = $obj;
275 my ($self, $otype) = @_;
280 if ($otype == PMG
::RuleDB
::Domain
::otype
()) {
281 $obj = PMG
::RuleDB
::Domain-
>new();
283 elsif ($otype == PMG
::RuleDB
::ReceiverDomain
::otype
) {
284 $obj = PMG
::RuleDB
::ReceiverDomain-
>new();
286 elsif ($otype == PMG
::RuleDB
::WhoRegex
::otype
) {
287 $obj = PMG
::RuleDB
::WhoRegex-
>new();
289 elsif ($otype == PMG
::RuleDB
::ReceiverRegex
::otype
) {
290 $obj = PMG
::RuleDB
::ReceiverRegex-
>new();
292 elsif ($otype == PMG
::RuleDB
::EMail
::otype
) {
293 $obj = PMG
::RuleDB
::EMail-
>new();
295 elsif ($otype == PMG
::RuleDB
::Receiver
::otype
) {
296 $obj = PMG
::RuleDB
::Receiver-
>new();
298 elsif ($otype == PMG
::RuleDB
::IPAddress
::otype
) {
299 $obj = PMG
::RuleDB
::IPAddress-
>new();
301 elsif ($otype == PMG
::RuleDB
::IPNet
::otype
) {
302 $obj = PMG
::RuleDB
::IPNet-
>new();
305 # elsif ($otype == Proxmox::RuleDB::LDAP::otype) {
306 # $obj = Proxmox::RuleDB::LDAP->new();
308 # elsif ($otype == Proxmox::RuleDB::LDAPUser::otype) {
309 # $obj = Proxmox::RuleDB::LDAPUser->new();
312 elsif ($otype == PMG
::RuleDB
::TimeFrame
::otype
) {
313 $obj = PMG
::RuleDB
::TimeFrame-
>new();
316 elsif ($otype == PMG
::RuleDB
::Spam
::otype
) {
317 $obj = PMG
::RuleDB
::Spam-
>new();
319 elsif ($otype == PMG
::RuleDB
::Virus
::otype
) {
320 $obj = PMG
::RuleDB
::Virus-
>new();
322 elsif ($otype == PMG
::RuleDB
::MatchField
::otype
) {
323 $obj = PMG
::RuleDB
::MatchField-
>new();
325 elsif ($otype == PMG
::RuleDB
::MatchFilename
::otype
) {
326 $obj = PMG
::RuleDB
::MatchFilename-
>new();
328 elsif ($otype == PMG
::RuleDB
::ContentTypeFilter
::otype
) {
329 $obj = PMG
::RuleDB
::ContentTypeFilter-
>new();
331 elsif ($otype == PMG
::RuleDB
::ArchiveFilter
::otype
) {
332 $obj = PMG
::RuleDB
::ArchiveFilter-
>new();
335 elsif ($otype == PMG
::RuleDB
::ModField
::otype
) {
336 $obj = PMG
::RuleDB
::ModField-
>new();
338 elsif ($otype == PMG
::RuleDB
::Accept
::otype
()) {
339 $obj = PMG
::RuleDB
::Accept-
>new();
341 elsif ($otype == PMG
::RuleDB
::ReportSpam
::otype
()) {
342 $obj = PMG
::RuleDB
::ReportSpam-
>new();
344 elsif ($otype == PMG
::RuleDB
::Attach
::otype
) {
345 $obj = PMG
::RuleDB
::Attach-
>new();
347 elsif ($otype == PMG
::RuleDB
::Disclaimer
::otype
) {
348 $obj = PMG
::RuleDB
::Disclaimer-
>new();
350 elsif ($otype == PMG
::RuleDB
::BCC
::otype
) {
351 $obj = PMG
::RuleDB
::BCC-
>new();
353 elsif ($otype == PMG
::RuleDB
::Quarantine
::otype
) {
354 $obj = PMG
::RuleDB
::Quarantine-
>new();
356 elsif ($otype == PMG
::RuleDB
::Block
::otype
) {
357 $obj = PMG
::RuleDB
::Block-
>new();
359 elsif ($otype == PMG
::RuleDB
::Counter
::otype
) {
360 $obj = PMG
::RuleDB
::Counter-
>new();
362 elsif ($otype == PMG
::RuleDB
::Remove
::otype
) {
363 $obj = PMG
::RuleDB
::Remove-
>new();
365 elsif ($otype == PMG
::RuleDB
::Notify
::otype
) {
366 $obj = PMG
::RuleDB
::Notify-
>new();
369 die "proxmox: unknown object type: ERROR";
375 sub load_counters_data
{
378 my $sth = $self->{dbh
}->prepare(
379 "SELECT Object.id, Objectgroup.name, Object.Value, Objectgroup.info " .
380 "FROM Object, Objectgroup " .
381 "WHERE objectgroup.id = object.objectgroup_id and ObjectType = ? " .
382 "order by Objectgroup.name, Value");
386 $sth->execute(PMG
::RuleDB
::Counter-
>otype());
388 while (my $ref = $sth->fetchrow_hashref()) {
389 my $tmp = [$ref->{id
},$ref->{name
},$ref->{value
},$ref->{info
}];
399 my ($self, $objid) = @_;
403 defined($objid) || die "undefined object id";
405 my $sth = $self->{dbh
}->prepare("SELECT * FROM Object where ID = ?");
406 $sth->execute($objid);
408 my $ref = $sth->fetchrow_hashref();
412 if (defined($ref->{'value'})) {
413 $value = $ref->{'value'};
416 if (!(defined($ref->{'objecttype'}) &&
417 defined($ref->{'objectgroup_id'}))) {
421 my $ogroup = $ref->{'objectgroup_id'};
423 my $otype = $ref->{'objecttype'};
424 my $obj = $self->get_object($otype);
426 $obj->load_attr($self, $objid, $ogroup, $value);
429 sub load_object_full
{
430 my ($self, $id, $gid, $exp_otype) = @_;
432 my $obj = $self->load_object($id);
433 die "object '$id' does not exists\n" if !defined($obj);
435 my $otype = $obj->otype();
436 die "wrong object type ($otype != $exp_otype)\n"
437 if defined($exp_otype) && $otype != $exp_otype;
439 die "wrong object group ($obj->{ogroup} != $gid)\n"
440 if $obj->{ogroup
} != $gid;
445 sub load_group_by_name
{
446 my ($self, $name) = @_;
448 my $sth = $self->{dbh
}->prepare("SELECT * FROM Objectgroup " .
451 $sth->execute($name);
453 while (my $ref = $sth->fetchrow_hashref()) {
454 my $og = PMG
::RuleDB
::Group-
>new($ref->{name
}, $ref->{info
},
456 $og->{id
} = $ref->{id
};
460 if ($ref->{'class'} eq 'action') {
461 my $objects = $self->load_group_objects($og->{id
});
462 my $obj = @$objects[0];
463 defined($obj) || die "undefined action object: ERROR";
464 $og->{action
} = $obj;
475 sub greylistexclusion_groupid
{
478 my $sth = $self->{dbh
}->prepare(
479 "select id from objectgroup where class='greylist' limit 1;");
483 my $ref = $sth->fetchrow_hashref();
488 sub load_group_objects
{
489 my ($self, $ogid) = @_;
491 defined($ogid) || die "undefined group id: ERROR";
493 my $sth = $self->{dbh
}->prepare(
494 "SELECT * FROM Object " .
495 "WHERE Objectgroup_ID = ? order by ObjectType,Value");
499 $sth->execute($ogid);
501 while (my $ref = $sth->fetchrow_hashref()) {
502 my $obj = $self->load_object($ref->{id
});
503 push @$objects, $obj;
513 my ($self, $obj) = @_;
520 sub group_add_object
{
521 my ($self, $group, $obj) = @_;
523 ($obj->oclass() eq $group->{class}) ||
524 die "wrong object class: ERROR";
526 $obj->{ogroup
} = $group->{id
};
528 $self->save_object($obj);
532 my ($self, $obj) = @_;
534 defined($obj->{id
}) || die "undefined object id";
538 $self->{dbh
}->begin_work;
540 $self->{dbh
}->do("DELETE FROM Attribut " .
541 "WHERE Object_ID = ?", undef, $obj->{id
});
543 $self->{dbh
}->do("DELETE FROM Object " .
547 $self->{dbh
}->commit;
550 $self->{dbh
}->rollback;
561 my ($self, $rule) = @_;
563 defined($rule->{name
}) ||
564 die "undefined rule attribute - name: ERROR";
565 defined($rule->{priority
}) ||
566 die "undefined rule attribute - priority: ERROR";
567 defined($rule->{active
}) ||
568 die "undefined rule attribute - active: ERROR";
569 defined($rule->{direction
}) ||
570 die "undefined rule attribute - direction: ERROR";
572 if (defined($rule->{id
})) {
576 "SET Name = ?, Priority = ?, Active = ?, Direction = ? " .
577 "WHERE ID = ?", undef,
578 $rule->{name
}, $rule->{priority
}, $rule->{active
},
579 $rule->{direction
}, $rule->{id
});
584 my $sth = $self->{dbh
}->prepare(
585 "INSERT INTO Rule (Name, Priority, Active, Direction) " .
586 "VALUES (?, ?, ?, ?);");
588 $sth->execute($rule->name, $rule->priority, $rule->active,
591 return $rule->{id
} = PMG
::Utils
::lastid
($self->{dbh
}, 'rule_id_seq');
598 my ($self, $ruleid) = @_;
600 defined($ruleid) || die "undefined rule id: ERROR";
603 $self->{dbh
}->begin_work;
605 $self->{dbh
}->do("DELETE FROM Rule " .
606 "WHERE ID = ?", undef, $ruleid);
607 $self->{dbh
}->do("DELETE FROM RuleGroup " .
608 "WHERE Rule_ID = ?", undef, $ruleid);
610 $self->{dbh
}->commit;
613 $self->{dbh
}->rollback;
621 sub delete_testrules
{
625 $self->{dbh
}->begin_work;
627 my $sth = $self->{dbh
}->prepare("Select id FROM Rule " .
628 "WHERE name = 'testrule'");
631 while(my $ref = $sth->fetchrow_hashref()) {
632 $self->{dbh
}->do("DELETE FROM Rule " .
633 "WHERE ID = ?", undef, $ref->{id
});
634 $self->{dbh
}->do("DELETE FROM RuleGroup " .
635 "WHERE Rule_ID = ?", undef, $ref->{id
});
639 $self->{dbh
}->commit;
642 $self->{dbh
}->rollback;
650 my ($self, $ruleid, $groupid, $gtype) = @_;
652 defined($ruleid) || die "undefined rule id: ERROR";
653 defined($groupid) || die "undefined group id: ERROR";
654 defined($gtype) || die "undefined group type: ERROR";
656 $self->{dbh
}->do("INSERT INTO RuleGroup " .
657 "(Objectgroup_ID, Rule_ID, Grouptype) " .
658 "VALUES (?, ?, ?)", undef,
659 $groupid, $ruleid, $gtype);
663 sub rule_add_from_group
{
664 my ($self, $rule, $group) = @_;
666 $self->rule_add_group($rule->{id
}, $group->{id
}, 0);
669 sub rule_add_to_group
{
670 my ($self, $rule, $group) = @_;
672 $self->rule_add_group($rule->{id
}, $group->{id
}, 1);
675 sub rule_add_when_group
{
676 my ($self, $rule, $group) = @_;
678 $self->rule_add_group($rule->{id
}, $group->{id
}, 2);
681 sub rule_add_what_group
{
682 my ($self, $rule, $group) = @_;
684 $self->rule_add_group($rule->{id
}, $group->{id
}, 3);
687 sub rule_add_action
{
688 my ($self, $rule, $group) = @_;
690 $self->rule_add_group($rule->{id
}, $group->{id
}, 4);
693 sub rule_remove_group
{
694 my ($self, $ruleid, $groupid, $gtype) = @_;
696 defined($ruleid) || die "undefined rule id: ERROR";
697 defined($groupid) || die "undefined group id: ERROR";
698 defined($gtype) || die "undefined group type: ERROR";
700 $self->{dbh
}->do("DELETE FROM RuleGroup WHERE " .
701 "Objectgroup_ID = ? and Rule_ID = ? and Grouptype = ?",
702 undef, $groupid, $ruleid, $gtype);
707 my ($self, $id) = @_;
709 defined($id) || die "undefined id: ERROR";
711 my $sth = $self->{dbh
}->prepare(
712 "SELECT * FROM Rule where id = ? ORDER BY Priority DESC");
718 my $ref = $sth->fetchrow_hashref();
719 die "rule '$id' does not exist\n" if !defined($ref);
721 my $rule = PMG
::RuleDB
::Rule-
>new($ref->{name
}, $ref->{priority
},
722 $ref->{active
}, $ref->{direction
});
723 $rule->{id
} = $ref->{id
};
731 my $sth = $self->{dbh
}->prepare(
732 "SELECT * FROM Rule ORDER BY Priority DESC");
738 while (my $ref = $sth->fetchrow_hashref()) {
739 my $rule = PMG
::RuleDB
::Rule-
>new($ref->{name
}, $ref->{priority
},
740 $ref->{active
}, $ref->{direction
});
741 $rule->{id
} = $ref->{id
};
758 The RuleDB Object manages the database connection and provides an interface to manipulate the database without SQL. A typical application first create a RuleDB object:
762 $ruledb = PMG::RuleDB->new();
764 =head2 Database Overview
768 Rules contains sets of Groups, grouped by classes (FROM, TO, WHEN, WHAT and ACTION). Each rule has an associated priority and and active/inactive marker.
772 A Group is a set of Objects.
776 Objects contains the filter data.
778 =head3 Rule Semantics
780 The classes have 'and' semantics. A rule matches if the checks in FROM, TO, WHEN and WHAT classes returns TRUE.
782 Within a class the objects are or'ed together.
784 =head2 Managing Rules
786 =head3 $ruledb->load_rules()
788 Returns an array of Rules containing all rules in the database.
790 =head3 $ruledb->save_rule ($rule)
792 One can use the following code to add a new rule to the database:
794 my $rule = PMG::RuleDB::Rule->new ($name, $priority, $active);
795 $ruledb->save_rule ($rule);
797 You can also use save_rule() to commit changes back to the database.
799 =head3 $ruledb->delete_rule ($ruleid)
801 Removes the rule from the database.
803 =head3 $ruledb->rule_add_group ($rule, $og, $gtype)
805 Add an object group to the rule.
807 Possible values for $gtype are:
809 0 = FROM, 1 = TO, 2 = WHEN, 3 = WHAT, 4 = ACTION
811 =head3 $ruledb->rule_remove_group ($rule, $og, $gtype)
813 Removes an object group from the rule.
815 =head2 Managing Objects and Groups
817 =head3 $ruledb->load_groups ($rule)
819 Return all object groups belonging to a rule. Data is divided into separate arrays:
821 my ($from, $to, $when, $what, $action) =
822 $ruledb->load_groups($rule);
824 =head3 $ruledb->save_group ($og)
826 This can be used to add or modify an Group. This code segemnt creates
829 $og = PMG::RuleDB::Group->new ($name, $desc);
830 $ruledb->save_group ($og);
833 =head3 $ruledb->delete_group ($groupid)
835 Deletes the object group, all reference to the group and all objects
836 belonging to this group from the Database.
838 =head3 $ruledb->group_add_object ($og, $obj)
840 Attach an object to an object group.
842 =head3 $ruledb->save_object ($obj)
844 Save or update an object. This can be used to add new objects
845 to the database (although group_add_object() is the prefered way):
847 $obj = PMG::RuleDB::EMail->new ('.*@mydomain.com');
848 # we need to set the object group manually
849 $obj->ogroup ($group->id);
850 $ruledb->save_object ($obj);
853 =head3 $ruledb->delete_object ($obj)
855 Deletes the object, all references to the object and all object
856 attributes from the database.