1 /*
2 
3                           Firewall Builder
4 
5                  Copyright (C) 2002 NetCitadel, LLC
6 
7   Author:  Vadim Kurland     vadim@fwbuilder.org
8 
9   $Id$
10 
11   This program is free software which we release under the GNU General Public
12   License. You may redistribute and/or modify this program under the terms
13   of that license as published by the Free Software Foundation; either
14   version 2 of the License, or (at your option) any later version.
15 
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20 
21   To get a copy of the GNU General Public License, write to the Free Software
22   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 
24 */
25 
26 #ifndef __POLICY_COMPILER_HH__
27 #define __POLICY_COMPILER_HH__
28 
29 #include "fwcompiler/Compiler.h"
30 #include "fwbuilder/Rule.h"
31 #include "fwbuilder/RuleElement.h"
32 
33 #include <string>
34 
35 namespace fwcompiler {
36 
37     #define DECLARE_POLICY_RULE_PROCESSOR(_Name) \
38         friend class _Name; \
39 	class _Name : public PolicyRuleProcessor { \
40 		public: \
41 		_Name(const std::string &n) :  \
42 			PolicyRuleProcessor(n) {}; \
43                 virtual ~_Name() {}; \
44 		virtual bool processNext(); \
45 	};
46 
47 
48     class PolicyCompiler : public Compiler {
49 
50 	protected:
51 
52 	/**
53 	 *  this method scans source_ruleset looking for atomic rule
54 	 *  which yields non-empty intersection with atomic rule r.
55 	 *
56 	 *  it can start scan either from the beginning of source_ruleset,
57 	 *  or from iterator 'start_here'
58 	 *
59 	 *  it returns iterator pointing at rule it has found (so we
60 	 *  can continue search later)
61 	 *
62 	 *  if parameter 'intersection' is not NULL, it is assumed to
63 	 *  be a pointer to a pointer at the object of class Rule. It
64 	 *  is used to return a pointer at intersection of rule 'rule'
65 	 *  and rule this function had found
66 	 */
67 	std::list<libfwbuilder::FWObject*>::iterator
68 	find_more_specific_rule(libfwbuilder::PolicyRule *r,
69                                 bool check_interface,
70                                 const std::list<libfwbuilder::FWObject*>::iterator &start_here,
71                                 const std::list<libfwbuilder::FWObject*>::iterator &stop_here,
72                                 libfwbuilder::PolicyRule **intersection=NULL);
73 
74 
75 	public:
76 
PolicyCompiler(libfwbuilder::FWObjectDatabase * _db,libfwbuilder::Firewall * fw,bool ipv6_policy,fwcompiler::OSConfigurator * _oscnf)77 	PolicyCompiler(libfwbuilder::FWObjectDatabase *_db,
78 		       libfwbuilder::Firewall *fw,
79                        bool ipv6_policy,
80 		       fwcompiler::OSConfigurator *_oscnf) :
81         Compiler(_db, fw, ipv6_policy, _oscnf) {}
82 
83         /**
84          * prints rule in some universal format (close to that visible
85          * to user in the GUI). Used for debugging purposes
86          */
87         virtual std::string debugPrintRule(libfwbuilder::Rule *rule);
88 
89 
90 	/**
91 	 * this method substracts atomic rule r2 from atomic rule r1.
92 	 * Resulting rule may have multiple objects in src,dst or srv,
93 	 * so converting to atomic may be necessary. If rules can not
94 	 * be compared, then it throws an exception. If resultant rule
95 	 * is empty, method returns rule with empty src,dst,srv
96 	 *
97 	 * NOT IMPLEMENTED YET
98 	 */
99 	libfwbuilder::Rule* getDifference(libfwbuilder::PolicyRule &r1,
100 					  libfwbuilder::PolicyRule &r2);
101 
102         /**
103          * detects if rule r2  shades rule r1
104          * returns:
105          *
106          *  true if r2 shades r1
107          */
108         bool checkForShadowing(libfwbuilder::PolicyRule &r1,
109                                libfwbuilder::PolicyRule &r2);
110 
111         /**
112          * virtual method to let policy compiler check rules using
113          * options specific for the given fw platform. Base class
114          * PolicyCompiler has no visibility into platform-specific
115          * options and can not do this.
116          */
117         virtual bool checkForShadowingPlatformSpecific(libfwbuilder::PolicyRule *r1,
118                                                        libfwbuilder::PolicyRule *r2);
119 
120 
121         /**
122          * compare interfaces of rules r1 and r2.
123          *
124          * Return true if r2 shadows r1 (only inetrface rule element
125          * is checked)
126          *
127          * If interface element is "all" (empty), it shadows any
128          * specific interface in the other rule, also "all" shadows
129          * "all". If neither is "all", return true if both rules refer
130          * the same interface, otherwise return false.
131          */
132         bool checkInterfacesForShadowing(libfwbuilder::PolicyRule &r1,
133                                          libfwbuilder::PolicyRule &r2);
134 
135         /**
136          * detects if rules r1 and r2 are identical (that is, have the
137          * same effect, rather than use the same objects)
138          *
139          * returns:
140          *
141          *  true if r1 is identical to r2
142          */
143         bool cmpRules(libfwbuilder::PolicyRule &r1,
144                       libfwbuilder::PolicyRule &r2);
145 
146 	/**
147 	 * this processor checks if the rule is associated with an
148 	 * interface and uses setInterfaceId to record its id. If the
149 	 * rule is associated with multiple interfaces, this processor
150 	 * splits the rule accordingly.
151 	 */
152         DECLARE_POLICY_RULE_PROCESSOR(InterfacePolicyRules);
153 
154 	/**
155 	 * this class expands groups in src,dst,srv. It creates
156 	 * references to new objects "in place" (that is, it does not
157 	 * create new rules but rather uses rule elements of the old
158 	 * ones)
159 	 */
160         DECLARE_POLICY_RULE_PROCESSOR(ExpandGroups);
161 
162 	/**
163 	 * expand groups in Srv
164 	 */
165         DECLARE_POLICY_RULE_PROCESSOR(expandGroupsInSrv);
166 
167 	/**
168 	 * expand groups in Interface rule element
169 	 */
170         DECLARE_POLICY_RULE_PROCESSOR(expandGroupsInItf);
171 
172         /**
173          *  this inspector replaces references to hosts and firewalls
174          *  in dst with references to their interfaces
175          */
176         class ExpandMultipleAddressesInSrc : public Compiler::expandMultipleAddressesInRE
177         {
178             public:
ExpandMultipleAddressesInSrc(const std::string & n)179             ExpandMultipleAddressesInSrc(const std::string &n) :
180                 expandMultipleAddressesInRE(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
181         };
182 
183         class ExpandMultipleAddressesInDst : public Compiler::expandMultipleAddressesInRE
184         {
185             public:
ExpandMultipleAddressesInDst(const std::string & n)186             ExpandMultipleAddressesInDst(const std::string &n) :
187                 expandMultipleAddressesInRE(n,libfwbuilder::RuleElementDst::TYPENAME) {}
188         };
189 
190 
191 
192 
193         class ReplaceFirewallObjectWithSelfInSrc : public Compiler::ReplaceFirewallObjectWithSelfInRE
194         {
195             public:
ReplaceFirewallObjectWithSelfInSrc(const std::string & n)196             ReplaceFirewallObjectWithSelfInSrc(const std::string &n) :
197                 ReplaceFirewallObjectWithSelfInRE(
198                     n, libfwbuilder::RuleElementSrc::TYPENAME) {}
199         };
200 
201         class ReplaceFirewallObjectWithSelfInDst : public Compiler::ReplaceFirewallObjectWithSelfInRE
202         {
203             public:
ReplaceFirewallObjectWithSelfInDst(const std::string & n)204             ReplaceFirewallObjectWithSelfInDst(const std::string &n) :
205                 ReplaceFirewallObjectWithSelfInRE(
206                     n, libfwbuilder::RuleElementDst::TYPENAME) {}
207         };
208 
209 
210 	/**
211          * single object negation in Src
212 	 */
213         class singleObjectNegationSrc : public singleObjectNegation
214         {
215             public:
singleObjectNegationSrc(const std::string & n)216             singleObjectNegationSrc(const std::string &n):
217                 singleObjectNegation(n, libfwbuilder::RuleElementSrc::TYPENAME)
218                 {}
219         };
220 
221 	/**
222          * single object negation in Dst
223 	 */
224         class singleObjectNegationDst : public Compiler::singleObjectNegation
225         {
226             public:
singleObjectNegationDst(const std::string & n)227             singleObjectNegationDst(const std::string &n):
228                 singleObjectNegation(n, libfwbuilder::RuleElementDst::TYPENAME)
229                 {}
230         };
231 
232 	/**
233          * single object negation in Itf
234 	 */
235         class singleObjectNegationItf : public Compiler::singleObjectNegation
236         {
237             public:
singleObjectNegationItf(const std::string & n)238             singleObjectNegationItf(const std::string &n):
239                 singleObjectNegation(n, libfwbuilder::RuleElementItf::TYPENAME)
240                 {}
241         };
242 
243 
244 	/**
245 	 * processes rules with negation in Itf.
246          * Compiler::fullInterfaceNegationInRE replaces interface object
247          * with a set of "other" interfaces of the firewall.
248 	 */
249         class ItfNegation : public Compiler::fullInterfaceNegationInRE
250         {
251             public:
ItfNegation(const std::string & name)252             ItfNegation(const std::string &name) :
253             fullInterfaceNegationInRE(
254                 name, libfwbuilder::RuleElementItf::TYPENAME) {}
255         };
256 
257 	/**
258 	 * replace cluster interface objects with inetrfaces of the member
259          * firewall in the Interface rule element
260 	 */
261         class replaceClusterInterfaceInItf : public Compiler::replaceClusterInterfaceInItfRE
262         {
263             public:
replaceClusterInterfaceInItf(const std::string & name)264             replaceClusterInterfaceInItf(const std::string &name) :
265             replaceClusterInterfaceInItfRE(
266                 name, libfwbuilder::RuleElementItf::TYPENAME) {}
267         };
268 
269 
270 	/**
271 	 *  this inspector replaces references to hosts and firewalls
272 	 *  in src or dst with references to their interfaces
273 	 *
274 	 * TODO: move to class Compiler because this might be useful
275 	 * for both PolicyCompiler and NATCompiler
276 	 */
277         DECLARE_POLICY_RULE_PROCESSOR(ExpandMultipleAddresses);
278 
279 	/**
280 	 * this processor splits rule element if src or dst contains
281 	 * address range
282 	 */
283         class addressRanges : public PolicyRuleProcessor
284         {
285             protected:
286             void expandAddressRangesInSrc(libfwbuilder::PolicyRule *rule);
287             void expandAddressRangesInDst(libfwbuilder::PolicyRule *rule);
288             public:
addressRanges(const std::string & name)289             addressRanges(const std::string &name) : PolicyRuleProcessor(name) {}
290             virtual bool processNext();
291         };
292 
293 
294 	/**
295 	 *  checks for unnumbered interface in rule elements (one can
296 	 *  not use unnumbered interfaces in rules). Call after
297 	 *  ExpandMultipleAddresses
298 	 */
299         class checkForUnnumbered : public PolicyRuleProcessor
300         {
301             public:
checkForUnnumbered(const std::string & n)302             checkForUnnumbered(const std::string &n) : PolicyRuleProcessor(n) {}
303             virtual bool processNext();
304         };
305 
306 	/**
307 	 * this processor converts to atomic rules using all combinations
308 	 * of objects in Src,Dst. It ignores Srv.
309 	 */
310         DECLARE_POLICY_RULE_PROCESSOR(ConvertToAtomicForAddresses);
311 
312 	/**
313 	 * this processor splits rule so that each atomic rule has
314 	 * exactly one Interval rule element
315 	 */
316         DECLARE_POLICY_RULE_PROCESSOR(ConvertToAtomicForIntervals);
317 
318 	/**
319 	 * this processor converts to atomic rules
320 	 */
321         DECLARE_POLICY_RULE_PROCESSOR(ConvertToAtomic);
322 
323         /**
324          *  deals with recursive groups in Src. See description for
325          *  Compiler::recursiveGroupsInRE
326          */
327         class recursiveGroupsInSrc : public Compiler::recursiveGroupsInRE
328         {
329             public:
recursiveGroupsInSrc(const std::string & n)330             recursiveGroupsInSrc(const std::string &n) :
331                 recursiveGroupsInRE(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
332         };
333 
334         /**
335          *  deals with recursive groups in Dst. See description for
336          *  Compiler::recursiveGroupsInRE
337          */
338         class recursiveGroupsInDst : public Compiler::recursiveGroupsInRE
339         {
340             public:
recursiveGroupsInDst(const std::string & n)341             recursiveGroupsInDst(const std::string &n) :
342                 recursiveGroupsInRE(n,libfwbuilder::RuleElementDst::TYPENAME) {}
343         };
344 
345         /**
346          *  deals with recursive groups in Srv. See description for
347          *  Compiler::recursiveGroupsInRE
348          */
349         class recursiveGroupsInSrv : public Compiler::recursiveGroupsInRE
350         {
351             public:
recursiveGroupsInSrv(const std::string & n)352             recursiveGroupsInSrv(const std::string &n) :
353                 recursiveGroupsInRE(n,libfwbuilder::RuleElementSrv::TYPENAME) {}
354         };
355 
356 
357 
358 
359         /**
360          *  deals with empty groups in Src. See description for
361          *  Compiler::emptyGroupsInRE
362          */
363         class emptyGroupsInSrc : public Compiler::emptyGroupsInRE
364         {
365             public:
emptyGroupsInSrc(const std::string & n)366             emptyGroupsInSrc(const std::string &n) :
367                 emptyGroupsInRE(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
368         };
369 
370         /**
371          *  deals with empty groups in Dst. See description for
372          *  Compiler::emptyGroupsInRE
373          */
374         class emptyGroupsInDst : public Compiler::emptyGroupsInRE
375         {
376             public:
emptyGroupsInDst(const std::string & n)377             emptyGroupsInDst(const std::string &n) :
378                 emptyGroupsInRE(n,libfwbuilder::RuleElementDst::TYPENAME) {}
379         };
380 
381         /**
382          *  deals with empty groups in Srv. See description for
383          *  Compiler::emptyGroupsInRE
384          */
385         class emptyGroupsInSrv : public Compiler::emptyGroupsInRE
386         {
387             public:
emptyGroupsInSrv(const std::string & n)388             emptyGroupsInSrv(const std::string &n) :
389                 emptyGroupsInRE(n,libfwbuilder::RuleElementSrv::TYPENAME) {}
390         };
391 
392         /**
393          *  deals with empty groups in Itf. See description for
394          *  Compiler::emptyGroupsInRE
395          */
396         class emptyGroupsInItf : public Compiler::emptyGroupsInRE
397         {
398             public:
emptyGroupsInItf(const std::string & n)399             emptyGroupsInItf(const std::string &n) :
400                 emptyGroupsInRE(n,libfwbuilder::RuleElementItf::TYPENAME) {}
401         };
402 
403 
404 	/**
405 	 * checks for host and network objects with address 0.0.0.0
406 	 */
407         class checkForZeroAddr : public PolicyRuleProcessor
408         {
409             libfwbuilder::Address *findHostWithNoInterfaces(libfwbuilder::RuleElement *re);
410             libfwbuilder::Address *findZeroAddress(libfwbuilder::RuleElement *re);
411             public:
checkForZeroAddr(const std::string & n)412             checkForZeroAddr(const std::string &n) : PolicyRuleProcessor(n) {}
413             virtual bool processNext();
414         };
415 
416         /**
417          * this is a base class for the family of rule processors that
418          * need to be able to find more general rule rule
419          */
420         class findMoreGeneralRule : public PolicyRuleProcessor
421         {
422             protected:
423             /**
424              *  this method scans tmp_queue looking for atomic rule
425              *  which is more general than atomic rule 'r'.
426              *
427              *  it can starts scan at position defined by iterator
428              *  start_here and ends it at the position given by
429              *  iterator stop_here
430              *
431              *  it returns iterator pointing at the rule it has found (so we
432              *  can continue search later)
433              */
434             std::deque<libfwbuilder::Rule*>::iterator
435             find_more_general_rule(libfwbuilder::PolicyRule *r,
436                                    bool check_interface,
437                                    const std::deque<libfwbuilder::Rule*>::iterator &start_here,
438                                    const std::deque<libfwbuilder::Rule*>::iterator &stop_here,
439                                    bool reverse=false);
440             public:
findMoreGeneralRule(const std::string & n)441             findMoreGeneralRule(const std::string &n) : PolicyRuleProcessor(n) {}
442         };
443 
444 
445 	/**
446 	 * this inspector scans rules and detects those which "shade"
447 	 * other rules below them
448 	 */
449         class DetectShadowing : public findMoreGeneralRule
450         {
451             std::deque<libfwbuilder::Rule*> rules_seen_so_far;
452             public:
DetectShadowing(const std::string & n)453             DetectShadowing(const std::string &n) : findMoreGeneralRule(n) {}
454             virtual bool processNext();
455         };
456 
457 	/**
458 	 * this inspector scans rules and detects those which "shade"
459 	 * other rules above them. Use for non-terminating rules.
460 	 */
461         class DetectShadowingForNonTerminatingRules : public findMoreGeneralRule
462         {
463             std::deque<libfwbuilder::Rule*> rules_seen_so_far;
464             public:
DetectShadowingForNonTerminatingRules(const std::string & n)465             DetectShadowingForNonTerminatingRules(const std::string &n) : findMoreGeneralRule(n) {}
466             virtual bool processNext();
467         };
468 
469 	/**
470 	 *  splits rule if one of the objects in Src is firewall
471 	 *  itself or a broadcast address for one of its interfaces or
472 	 *  multicast (multicast support is not implemented yet). This
473 	 *  is needed to properly choose direction and chain
474 	 *  later. Src may have multiple objects when this processor
475 	 *  is called.  For firewall the iptables code compiler
476 	 *  generates should go into OUTPUT chain, while for all other
477 	 *  objects it should go into FORWARD chain. That is why we
478 	 *  need to split the rule and place firewall object in the
479 	 *  src of the rule of its own.
480 	 */
481         class splitIfSrcMatchesFw : public Compiler::splitIfRuleElementMatchesFW
482         {
483             public:
splitIfSrcMatchesFw(const std::string & n)484             splitIfSrcMatchesFw (const std::string &n) :
485                 splitIfRuleElementMatchesFW(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
486         };
487 
488 
489 	/**
490 	 *  splits rule if one of the objects in Dst is firewall
491 	 *  itself. This is needed to properly choose direction and
492 	 *  chain later. See comment in splitIfInputChainObjectSrc.
493 	 */
494         class splitIfDstMatchesFw : public Compiler::splitIfRuleElementMatchesFW
495         {
496             public:
splitIfDstMatchesFw(const std::string & n)497             splitIfDstMatchesFw (const std::string &n) :
498                 splitIfRuleElementMatchesFW(n,libfwbuilder::RuleElementDst::TYPENAME) {}
499         };
500 
501 
502 	/**
503 	 * many firewall platforms do not support filtering by MAC
504 	 * addresses. Issue warning if MAC address is used in the rule
505 	 * and remove it from the rule element.
506          *
507          * Call this processor after ExpandMultipleAddresses.
508 	 */
509         class MACFiltering : public PolicyRuleProcessor
510         {
511             protected:
512             std::string last_rule_lbl;
513 /* return value:
514  * true  - ok
515  * false - one or more MAC addresses have been removed, issue warning
516  */
517             bool  checkRuleElement(libfwbuilder::RuleElement *re);
518             public:
MACFiltering(const std::string & n)519             MACFiltering(const std::string &n) : PolicyRuleProcessor(n) {}
520             virtual bool processNext();
521         };
522 
523 
524         /**
525          * rule processors that replace MultiAddress objects with MultiAddressRunTime
526          * equivalents
527          */
528         class swapMultiAddressObjectsInSrc : public Compiler::swapMultiAddressObjectsInRE
529         {
530             public:
swapMultiAddressObjectsInSrc(const std::string & n)531             swapMultiAddressObjectsInSrc(const std::string &n) :
532                 swapMultiAddressObjectsInRE(n,libfwbuilder::RuleElementSrc::TYPENAME) {}
533         };
534 
535         class swapMultiAddressObjectsInDst : public Compiler::swapMultiAddressObjectsInRE
536         {
537             public:
swapMultiAddressObjectsInDst(const std::string & n)538             swapMultiAddressObjectsInDst(const std::string &n) :
539                 swapMultiAddressObjectsInRE(n,libfwbuilder::RuleElementDst::TYPENAME) {}
540         };
541 
542         class RegisterGroupsAndTablesInSrc : public RegisterGroupsAndTablesInRE
543         {
544             public:
RegisterGroupsAndTablesInSrc(const std::string & n)545             RegisterGroupsAndTablesInSrc(const std::string &n) :
546             RegisterGroupsAndTablesInRE(n, libfwbuilder::RuleElementSrc::TYPENAME)
547             {}
548         };
549 
550         class RegisterGroupsAndTablesInDst : public RegisterGroupsAndTablesInRE
551         {
552             public:
RegisterGroupsAndTablesInDst(const std::string & n)553             RegisterGroupsAndTablesInDst(const std::string &n) :
554             RegisterGroupsAndTablesInRE(n, libfwbuilder::RuleElementDst::TYPENAME)
555             {}
556         };
557 
558 
559 	virtual int prolog();
560 
561     };
562 
563 
564 };
565 
566 #endif
567