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 __COMPILER_HH__
27 #define __COMPILER_HH__
28 
29 #include "config.h"
30 #include "fwbuilder/libfwbuilder-config.h"
31 #include "fwbuilder/FWObjectDatabase.h"
32 #include "fwbuilder/FWException.h"
33 
34 #include "fwcompiler/BaseCompiler.h"
35 #include "fwcompiler/RuleProcessor.h"
36 #include "fwcompiler/exceptions.h"
37 #include "fwcompiler/GroupRegistry.h"
38 
39 #include <list>
40 #include <vector>
41 #include <map>
42 
43 #include <fstream>
44 #include <sstream>
45 
46 namespace libfwbuilder {
47     class FWObject;
48     class FWOptions;
49     class FWObjectDatabase;
50     class InetAddr;
51     class Address;
52     class Cluster;
53     class FailoverClusterGroup;
54     class StateSyncClusterGroup;
55     class Service;
56     class Interval;
57     class IPv4;
58     class IPv6;
59     class Network;
60     class NetworkIPv6;
61     class AddressRange;
62     class Host;
63     class physAddress;
64     class Firewall;
65     class Interface;
66     class Rule;
67     class RuleSet;
68     class PolicyRule;
69     class NATRule;
70     class RuleElement;
71 };
72 
73 
74 namespace fwcompiler {
75 
76     class OSConfigurator;
77 
78 /*
79  * operations    (see Compiler_ops.cc)
80  */
81 
82     /**
83      * this operator compares two objects to determine if they are
84      * equivalent
85      */
86     bool operator==(const libfwbuilder::Address &o1,const libfwbuilder::Address &o2);
87     bool operator==(const libfwbuilder::Service &o1,const libfwbuilder::Service &o2);
88     bool operator==(const libfwbuilder::Interval &o1,const libfwbuilder::Interval &o2);
89 
90     /**
91      * this method finds intersection of two objects. Objects must
92      * be of such types that have address (Host, Firewall,
93      * Interface, Network) , otherwise it throws an exception
94      *
95      * TODO:  implement this as a virtual method of respective classes
96      *
97      * this method is intended for internal use only
98      */
99     std::vector<libfwbuilder::FWObject*>
100     _find_obj_intersection(libfwbuilder::Address *o1,
101 			   libfwbuilder::Address *o2);
102     /**
103      * this method finds intersection of two services. If one or
104      * both objects are not services, it throws exception
105      *
106      * this method is intended for internal use only
107      */
108     std::vector<libfwbuilder::FWObject*>
109     _find_srv_intersection(libfwbuilder::Service *o1,
110 			   libfwbuilder::Service *o2);
111 
112     /**
113      * this method finds intersection of two ranges of ports
114      *
115      * this method is intended for internal use only
116      */
117     bool _find_portrange_intersection(int rs1,int re1,int rs2,int re2,int &rsr,int &rer);
118 
119     struct threeTuple {
120         libfwbuilder::Address *src;
121         libfwbuilder::Address *dst;
122         libfwbuilder::Service *srv;
123     };
124 
125     class Compiler : public BaseCompiler
126     {
127         void _init(libfwbuilder::FWObjectDatabase *_db, libfwbuilder::Firewall *fw);
128 
129         virtual void _expand_group_recursive(libfwbuilder::FWObject *o,
130                                              std::list<libfwbuilder::FWObject*> &ol);
131 
132         virtual void _expand_addr_recursive(libfwbuilder::Rule *rule,
133                                             libfwbuilder::FWObject *s,
134                                             std::list<libfwbuilder::FWObject*> &ol,
135                                             bool expand_cluster_interfaces_fully);
136 
137         /* bool _complexMatchWithInterface(libfwbuilder::Address   *obj1, */
138         /*                                 libfwbuilder::Interface *iface, */
139         /*                                 bool recognize_broadcasts=true); */
140 
141         /* bool _complexMatchWithAddress(const libfwbuilder::InetAddr *obj1_addr, */
142         /*                               libfwbuilder::Interface *iface, */
143         /*                               const std::string &address_type, */
144         /*                               bool recognize_broadcasts); */
145 
146         bool checkIfAddressesMatch(const libfwbuilder::Address *a1,
147                                    const libfwbuilder::Address *a2);
148 
149 protected:
150 
151         int  _cntr_;
152         bool initialized;
153         int countIPv6Rules;
154         bool ipv6;
155         std::map<int, bool> object_comparison_cache;
156         std::map<int, threeTuple*> rule_elements_cache;
157 
158         std::list<BasicRuleProcessor*> rule_processors;
159 
160         /**
161          * if object <o> is Address, check if it matches address family
162          * (i.e. if it is IPv6 or IPv4). If it is service, always return true.
163          */
164         bool MatchesAddressFamily(libfwbuilder::FWObject *o);
165 
166         /**
167          * this method finds intersection of two atomic rules. Resulting
168          * rule may have multiple objects in src,dst and srv, so
169          * converting to atomic may be necessary. If rules can not be
170          * compared, then it throws an exception. If rules are compatible
171          * but have nothing in common, then this method returns rule with
172          * empty src,dst,srv. Use isEmpty(Rule &r) to check for this
173          * condition
174          *
175          * This method creates and returns new object of class Rule
176          * and does not modify r1 and r2
177          *
178          * This method works only with interface, src, dst and srv and
179          * completely ignores action and other rule options.
180          *
181          */
182         void  getIntersection(libfwbuilder::PolicyRule &r1,
183                               libfwbuilder::PolicyRule &r2,
184                               libfwbuilder::PolicyRule &res);
185 
186         /**
187          * this function checks if two rules intersect - that is, if there
188          * is a non-empty intersection for each rule element. This
189          * function does not calculate intersection, it just verifies that
190          * it does exsit.
191          */
192         bool  intersect(libfwbuilder::PolicyRule &r1,
193                         libfwbuilder::PolicyRule &r2);
194 
195 
196         /**
197          * add rule processor to the list
198          */
199         void add(BasicRuleProcessor* rp);
200 
201         /**
202          *  assembles chain of rule processors and executes it
203          */
204         void runRuleProcessors();
205 
206         /**
207          *  deletes chain of rule processors
208          */
209         void deleteRuleProcessors();
210 
211        /*
212         * the following variables are simply a cache for frequently used
213         * objects
214         */
215         int                                     fw_id;
216         libfwbuilder::FWOptions                *fwopt;
217 
218 public:
219 
220 	int  debug;
221 	int  debug_rule;
222         bool rule_debug_on;
223 	bool verbose;
224         bool single_rule_mode;
225         std::string single_rule_ruleset_name;
226         int single_rule_position;
227         libfwbuilder::Rule *single_rule_compile_rule;
228 
229 	fwcompiler::OSConfigurator *osconfigurator;
230 	libfwbuilder::FWObjectDatabase *dbcopy;
231 	libfwbuilder::Library *persistent_objects;
232 	libfwbuilder::Firewall *fw;
233 
234         // group registry is optional, the object shuld be created outside
235         // of the compiler and set using function setGroupRegistry().
236         GroupRegistry *group_registry;
237 
238         std::string ruleSetName;;
239 
240 	libfwbuilder::RuleSet *source_ruleset;
241 	libfwbuilder::RuleSet *temp_ruleset;
242 
243         libfwbuilder::Group *temp;
244 
245 	std::stringstream output;
246 
247         void registerGroupObject(libfwbuilder::RuleElement *re,
248                                  libfwbuilder::ObjectGroup *grp);
249 
registerIPv6Rule()250         void registerIPv6Rule() { countIPv6Rules++; }
haveIPv6Rules()251         bool haveIPv6Rules() { return countIPv6Rules > 0; }
252 
253         /**
254          * returns first object referenced by given rule
255          * element. Dereferences FWReference if first object is
256          * reference. Uses cache, therefore is faster than
257          * RuleElement::getFirst(true)
258          */
259         libfwbuilder::Address* getFirstSrc(libfwbuilder::PolicyRule *rule);
260         libfwbuilder::Address* getFirstDst(libfwbuilder::PolicyRule *rule);
261         libfwbuilder::Service* getFirstSrv(libfwbuilder::PolicyRule *rule);
262         libfwbuilder::Interval* getFirstWhen(libfwbuilder::PolicyRule *rule);
263         libfwbuilder::Interface* getFirstItf(libfwbuilder::PolicyRule *rule);
264 
265         libfwbuilder::Address* getFirstOSrc(libfwbuilder::NATRule *rule);
266         libfwbuilder::Address* getFirstODst(libfwbuilder::NATRule *rule);
267         libfwbuilder::Service* getFirstOSrv(libfwbuilder::NATRule *rule);
268 
269         libfwbuilder::Address* getFirstTSrc(libfwbuilder::NATRule *rule);
270         libfwbuilder::Address* getFirstTDst(libfwbuilder::NATRule *rule);
271         libfwbuilder::Service* getFirstTSrv(libfwbuilder::NATRule *rule);
272 
273         /**
274          * these methods compare two objects to determine if one of them
275          * "shades" the other
276          */
277         bool checkForShadowing(const libfwbuilder::Address &o1,
278                                const libfwbuilder::Address &o2);
279         bool checkForShadowing(const libfwbuilder::Service &o1,
280                                const libfwbuilder::Service &o2);
resetObjectComparisonCache()281         void resetObjectComparisonCache() { object_comparison_cache.clear(); }
282 
283 	/**
284 	 *   a method to check for unnumbered interface in a rule
285 	 *   element (one can not use unnumbered interfaces in rules).
286 	 */
287         bool catchUnnumberedIfaceInRE(libfwbuilder::RuleElement *re);
288 
289         /**
290          * return true if any address object in source or destination is
291          * of given type (can be IPv4 or IPv6).
292          */
293         bool FindAddressFamilyInRE(libfwbuilder::FWObject *re, bool ipv6);
294 
295         /**
296          * find ipv6 or ipv4 address objects in the given rule element
297          * and remove reference to them
298          */
299         void DropAddressFamilyInRE(libfwbuilder::RuleElement *rel,
300                                    bool drop_ipv6);
301 
302         /**
303          * similarly, remove reference to objects in service rule elements
304          * based on their compatibility with ipv6 context.
305          */
306         void DropByServiceTypeInRE(libfwbuilder::RuleElement *rel,
307                                    bool drop_ipv6);
308 
309         /**
310          *  rule processor that "injects" rules into the conveyor
311          */
312         class Begin : public BasicRuleProcessor
313         {
314             bool init;
315             public:
316             Begin();
317             Begin(const std::string &n);
318             virtual bool processNext();
319         };
320 
321 	/**
322 	 * this processor prints number of rules in the queue on cout
323 	 * if compiler->verbose is true
324 	 */
325         class printTotalNumberOfRules : public BasicRuleProcessor
326         {
327             public:
328             virtual bool processNext();
329         };
330 
331 	/**
332 	 * this processor creates what amounts to the new compiler
333 	 * pass: it slurps all rules into buffer, then prints its own
334 	 * name on cout and the releases rules to the next processor
335 	 * one at a time.  This way processors after this one in the
336 	 * chain get to start working on the whole rule set from its
337 	 * beginning.
338 	 */
339         class createNewCompilerPass : public BasicRuleProcessor
340         {
341             std::string pass_name;
342             public:
createNewCompilerPass(const std::string & _name)343             createNewCompilerPass(const std::string &_name) : BasicRuleProcessor("New compiler pass") { pass_name=_name; };
344             virtual bool processNext();
345         };
346 
347 	/**
348 	 * this processor prints rule numbers on cout (trivial
349 	 * progress indicator)
350 	 */
351         class simplePrintProgress : public BasicRuleProcessor
352         {
353             std::string current_rule_label;
354             public:
simplePrintProgress()355             simplePrintProgress() : BasicRuleProcessor("Print progress") {};
356             virtual bool processNext();
357         };
358 
359         /**
360          * this processor splits rule if one of its rule elements
361          * contains firewall itself. This processor is actually only a
362          * base class. Derive it and pass rule element type name as a
363          * second argument of its constructor.
364          */
365         class splitIfRuleElementMatchesFW : public PolicyRuleProcessor
366         {
367             std::string re_type;
368             public:
splitIfRuleElementMatchesFW(const std::string & n,std::string _type)369             splitIfRuleElementMatchesFW(const std::string &n,
370                                                   std::string _type) :
371                 PolicyRuleProcessor(n) { re_type=_type; }
372             virtual bool processNext();
373         };
374 
375         /**
376          * prepare for negation of single objects in rule elements
377          */
378         class singleObjectNegation : public BasicRuleProcessor
379         {
380             std::string re_type;
381             public:
singleObjectNegation(const std::string & n,std::string _type)382             singleObjectNegation(const std::string &n,std::string _type):
383                 BasicRuleProcessor(n) { re_type=_type; }
384             virtual bool processNext();
385         };
386 
387         /*
388          * replace interfaces in the give RE with a set of all other
389          * interfaces of the firewall.
390          */
391         class fullInterfaceNegationInRE : public BasicRuleProcessor
392         {
393             std::string re_type;
394             public:
fullInterfaceNegationInRE(const std::string & n,std::string _type)395                 fullInterfaceNegationInRE(const std::string &n, std::string _type) :
396                     BasicRuleProcessor(n) { re_type=_type; }
397             virtual bool processNext();
398         };
399 
400 	/**
401 	 * replace cluster interface objects with inetrfaces of the member
402          * firewall in the Interface rule element
403 	 */
404         class replaceClusterInterfaceInItfRE : public BasicRuleProcessor
405         {
406             std::string re_type;
407             public:
replaceClusterInterfaceInItfRE(const std::string & n,std::string _type)408                 replaceClusterInterfaceInItfRE(const std::string &n,
409                                                std::string _type) :
410                 BasicRuleProcessor(n) { re_type=_type; }
411             virtual bool processNext();
412         };
413 
414         /**
415          *  eliminates duplicates in RuleElement 're_type'. Inherit
416          *  your own class using this one and supply actual rule
417          *  element type name through its constructor.
418          *
419          *  Function class equalObj compares IDs of two object and
420          *  declares objects equal if their ID are the same.  To
421          *  change comparison algorithm, inherit from this class,
422          *  overload its operator(), then create its instance in
423          *  constructor of eliminateDuplicatesInRE and assign to
424          *  member 'comparator'
425          */
426         class equalObj {
427             protected:
428             libfwbuilder::FWObject *obj;
429             public:
equalObj()430             equalObj(){obj=NULL;}
~equalObj()431             virtual ~equalObj() {}
set(libfwbuilder::FWObject * o)432             void set(libfwbuilder::FWObject *o) {obj=o;}
433             virtual bool operator()(libfwbuilder::FWObject *o);
434         };
435 
436         class eliminateDuplicatesInRE : public BasicRuleProcessor
437         {
438             std::string re_type;
439             protected:
440             equalObj *comparator;
441             public:
eliminateDuplicatesInRE(const std::string & n,const std::string _type)442             eliminateDuplicatesInRE(const std::string &n,const std::string _type):
443                 BasicRuleProcessor(n) { re_type=_type; comparator=NULL; }
~eliminateDuplicatesInRE()444             ~eliminateDuplicatesInRE() { if (comparator!=NULL) delete comparator; }
445             virtual bool processNext();
446         };
447 
448         /**
449          * this processor checks for recursive groups, i.e. groups
450          * that reference themselves
451          */
452         class recursiveGroupsInRE : public BasicRuleProcessor
453         {
454             std::string re_type;
455             void isRecursiveGroup(int grid, libfwbuilder::FWObject *gr);
456             public:
recursiveGroupsInRE(const std::string & n,const std::string & _type)457             recursiveGroupsInRE(const std::string &n,const std::string &_type) :
458                 BasicRuleProcessor(n) { re_type=_type; }
459             virtual bool processNext();
460         };
461 
462 
463 	/**
464 	 * This rule processor checks for empty groups. Normally this
465 	 * is a fatal error and compilation should be aborted, but
466 	 * firewall option "ignore_rules_with_empty_groups" causes
467 	 * compiler to remove this object from the rule element and
468 	 * drop the rule all together if there are no more objects
469 	 * left (rule element becomes "any") and continue work
470 	 * (warning should be issued though).
471 	 */
472         class emptyGroupsInRE : public BasicRuleProcessor
473         {
474             std::string re_type;
475             int  countChildren(libfwbuilder::FWObject *obj);
476             void findEmptyGroupsInRE();
477             public:
emptyGroupsInRE(const std::string & n,const std::string & _type)478             emptyGroupsInRE(const std::string &n,const std::string &_type) :
479                 BasicRuleProcessor(n) { re_type=_type; }
480             virtual bool processNext();
481         };
482 
483 
484         /**
485          * Replace MultiAddress objects that require run-time address
486          * expansion with corresponding MultiAddressRunTime objects
487          */
488         class swapMultiAddressObjectsInRE : public BasicRuleProcessor
489         {
490             std::string re_type;
491             public:
swapMultiAddressObjectsInRE(const std::string & name,const std::string & t)492             swapMultiAddressObjectsInRE(const std::string &name,
493                       const std::string &t) : BasicRuleProcessor(name) { re_type=t; }
494             virtual bool processNext();
495         };
496 
497         /**
498          *  this inspector replaces references to hosts and firewalls
499          *  in rule element with references to their interfaces
500          */
501         class expandMultipleAddressesInRE : public BasicRuleProcessor
502         {
503             std::string re_type;
504             public:
expandMultipleAddressesInRE(const std::string & name,const std::string & t)505             expandMultipleAddressesInRE(const std::string &name,
506                                         const std::string &t) :
507                 BasicRuleProcessor(name) { re_type=t; }
508             virtual bool processNext();
509         };
510 
511         /**
512          * drop rules that have ipv4 or ipv6 addresses  (depending
513          * on the argument ipv6 passed to the constructor)
514          */
515         class DropRulesByAddressFamilyAndServiceType : public BasicRuleProcessor
516         {
517             std::string warning_str;
518             bool drop_ipv6;
519             public:
DropRulesByAddressFamilyAndServiceType(const std::string & n,bool ipv6)520             DropRulesByAddressFamilyAndServiceType(
521                 const std::string &n, bool ipv6) : BasicRuleProcessor(n)
522             { drop_ipv6 = ipv6; warning_str = ""; }
523             virtual bool processNext();
524             protected:
DropRulesByAddressFamilyAndServiceType(const std::string & n,const std::string & w,bool ipv6)525             DropRulesByAddressFamilyAndServiceType(
526                 const std::string &n,
527                 const std::string &w,
528                 bool ipv6) : BasicRuleProcessor(n)
529             { drop_ipv6 = ipv6; warning_str = w; }
530         };
531 
532         /**
533          * Drop rule if any address object in source or destination is
534          * ipv4 address.
535          */
536         class DropIPv4Rules : public DropRulesByAddressFamilyAndServiceType
537         {
538             public:
DropIPv4Rules(const std::string & n)539             DropIPv4Rules(const std::string &n) :
540               DropRulesByAddressFamilyAndServiceType(n, false) {};
541         };
542 
543         /**
544          * Drop rule if any address object in source or destination is
545          * ipv6 address.
546          */
547         class DropIPv6Rules : public DropRulesByAddressFamilyAndServiceType
548         {
549             public:
DropIPv6Rules(const std::string & n)550             DropIPv6Rules(const std::string &n) :
551               DropRulesByAddressFamilyAndServiceType(n, true) {};
552         };
553 
554         class DropIPv6RulesWithWarning : public DropRulesByAddressFamilyAndServiceType
555         {
556             public:
DropIPv6RulesWithWarning(const std::string & n,const std::string & w)557             DropIPv6RulesWithWarning(const std::string &n, const std::string &w) :
558                 DropRulesByAddressFamilyAndServiceType(n, w, true) {};
559         };
560 
561         /**
562 	 * drop rules that have empty rule elements
563 	 */
564         class dropRuleWithEmptyRE : public BasicRuleProcessor
565         {
566             std::string warning_str;
567             bool isREEmpty(libfwbuilder::Rule *rule, const std::string &re_type);
568             public:
dropRuleWithEmptyRE(const std::string & name)569             dropRuleWithEmptyRE(const std::string &name) :
570                 BasicRuleProcessor(name) { warning_str = ""; }
571             virtual bool processNext();
572             protected:
dropRuleWithEmptyRE(const std::string & name,const std::string & _warning)573             dropRuleWithEmptyRE(const std::string &name,
574                                 const std::string &_warning) :
575                 BasicRuleProcessor(name) { warning_str = _warning; }
576         };
577 
578         class dropRuleWithEmptyREWithWarning : public dropRuleWithEmptyRE
579         {
580             public:
dropRuleWithEmptyREWithWarning(const std::string & name,const std::string & _warning)581             dropRuleWithEmptyREWithWarning(const std::string &name,
582                                 const std::string &_warning) :
583                 dropRuleWithEmptyRE(name, _warning) { }
584         };
585 
586         /**
587          * if MultiAddress object failed to convert itself to a group
588          * of addresses and compiler runs in a test mode, we use dummy
589          * test addresses instead. The error is detected by
590          * preprocessor and at the moment not associated with any rule
591          * (because preprocessor works with MultiAddress objects and
592          * does not check which rule they are used in to improve
593          * performance).  This processor adds error message to the
594          * rule using MultiAddress obejct like this.
595          */
596         class checkForObjectsWithErrors : public BasicRuleProcessor
597         {
598             public:
checkForObjectsWithErrors(const std::string & name)599             checkForObjectsWithErrors(const std::string &name)
600                 : BasicRuleProcessor(name) {}
601             virtual bool processNext();
602         };
603 
604         /**
605          * Replace cluster interface object with corresponding real
606          * interface
607          */
608         class replaceFailoverInterfaceInRE : public BasicRuleProcessor
609         {
610             std::string re_type;
611             public:
replaceFailoverInterfaceInRE(const std::string & name,const std::string & t)612             replaceFailoverInterfaceInRE(const std::string &name,
613                       const std::string &t) : BasicRuleProcessor(name) { re_type=t; }
614             virtual bool processNext();
615         };
616 
617 	/**
618 	 * generic rule debugger: prints name of the previous rule
619 	 * processor in a chain and then a rule if its number is
620 	 * compiler->debug_rule.  Uses virtual method
621 	 * Compiler::debugPrintRule to actually print the rule
622 	 */
623         class Debug : public BasicRuleProcessor
624         {
625             public:
626             virtual bool processNext();
627         };
628 
629 	/**
630          * this rule processor skips all rules except the one with ID
631          * set by call to setSingleRuleMode()
632 	 */
633         class singleRuleFilter : public BasicRuleProcessor
634         {
635             public:
636             virtual bool processNext();
637         };
638 
639 	/**
640 	 * split rules with more than one service object, so that each
641 	 * rule has services that satisfy some common criteria defined by
642          * the virtual function groupingCode()
643 	 */
644         class groupServices : public BasicRuleProcessor
645         {
646             protected:
647             virtual int groupingCode(const libfwbuilder::Service *srv) =0;
648             public:
groupServices(const std::string & name)649             groupServices(const std::string &name) : BasicRuleProcessor(name) {}
650             virtual bool processNext();
651         };
652 
653 	/**
654 	 * split rules with more than one service object, so that each
655 	 * rule has services with the same protocol
656 	 */
657         class groupServicesByProtocol: public groupServices
658         {
659             protected:
660             virtual int groupingCode(const libfwbuilder::Service *srv);
661             public:
groupServicesByProtocol(const std::string & name)662             groupServicesByProtocol(const std::string &name) : groupServices(name){}
663         };
664 
665 	/**
666 	 * split rules with more than one service object, so that all
667 	 * tcp and udp services are in one rule and all other
668 	 * protocols are in the other
669 	 */
670         class groupTCPUDPServices: public groupServices
671         {
672             protected:
673             virtual int groupingCode(const libfwbuilder::Service *srv);
674             public:
groupTCPUDPServices(const std::string & name)675             groupTCPUDPServices(const std::string &name) : groupServices(name){}
676         };
677 
678         /**
679 	 * separate service object that satisfies condition
680 	 * implemented in the virtual method "condition" so we have
681 	 * exactly one such object per rule.
682 	 */
683         class separateServiceObject : public BasicRuleProcessor
684         {
685             protected:
686             virtual bool condition(const libfwbuilder::Service *srv) =0;
687             public:
688             separateServiceObject(const std::string &name);
689             virtual bool processNext();
690         };
691 
692 	/**
693 	 * separate TCP/UDP services (regardless of their source or
694 	 * destination port configuration)
695 	 */
696         class separateTCPUDP : public separateServiceObject
697         {
698             protected:
699             virtual bool condition(const libfwbuilder::Service *srv);
700             public:
separateTCPUDP(const std::string & name)701             separateTCPUDP(const std::string &name) :
702                 separateServiceObject(name) {}
703         };
704 
705 	/**
706 	 * separate TCP/UDP services that specify source port (can
707 	 * not be used in combination with destination port with
708 	 * multiport)
709 	 */
710         class separateSrcPort : public separateServiceObject
711         {
712             protected:
713             virtual bool condition(const libfwbuilder::Service *srv);
714             public:
separateSrcPort(const std::string & name)715             separateSrcPort(const std::string &name) :
716                 separateServiceObject(name) {}
717         };
718 
719 	/**
720 	 * separate TCP/UDP services that specify both source and
721 	 * destination port
722 	 */
723         class separateSrcAndDstPort : public separateServiceObject
724         {
725             protected:
726             virtual bool condition(const libfwbuilder::Service *srv);
727             public:
separateSrcAndDstPort(const std::string & name)728             separateSrcAndDstPort(const std::string &name) :
729                 separateServiceObject(name) {}
730         };
731         /**
732 	 * separate Tag services so we have exactly one per rule.
733 	 */
734         class separateTagged : public separateServiceObject
735         {
736             protected:
737             virtual bool condition(const libfwbuilder::Service *srv);
738             public:
separateTagged(const std::string & name)739             separateTagged(const std::string &name) :
740                 separateServiceObject(name) {}
741         };
742 
743         /**
744 	 * separate Custom services so we have exactly one per rule.
745 	 */
746         class separateCustom : public separateServiceObject
747         {
748             protected:
749             virtual bool condition(const libfwbuilder::Service *srv);
750             public:
separateCustom(const std::string & name)751             separateCustom(const std::string &name) :
752                 separateServiceObject(name) {}
753         };
754 
755         class separateUserServices : public separateServiceObject
756         {
757             protected:
758             virtual bool condition(const libfwbuilder::Service *srv);
759             public:
separateUserServices(const std::string & name)760             separateUserServices(const std::string &name) :
761                 separateServiceObject(name) {}
762         };
763 
764         /**
765 	 * separate IPService objects with tos attrubute so we have
766 	 * exactly one per rule.
767 	 */
768         class separateTOS : public separateServiceObject
769         {
770             protected:
771             virtual bool condition(const libfwbuilder::Service *srv);
772             public:
separateTOS(const std::string & name)773             separateTOS(const std::string &name) :
774                 separateServiceObject(name) {}
775         };
776 
777         /**
778 	 * split rules with more than one IPService object with
779 	 * options, so that each rule has only one such service
780 	 */
781         class splitIpOptions : public separateServiceObject
782         {
783             protected:
784             virtual bool condition(const libfwbuilder::Service *srv);
785             public:
splitIpOptions(const std::string & name)786             splitIpOptions(const std::string &name) :
787                 separateServiceObject(name) {}
788         };
789 
790 	/**
791 	 * separate TCP services with flags (can't use those in combination
792 	 * with others in groups of services)
793 	 */
794         class separateTCPWithFlags : public separateServiceObject
795         {
796             protected:
797             virtual bool condition(const libfwbuilder::Service *srv);
798             public:
separateTCPWithFlags(const std::string & name)799             separateTCPWithFlags(const std::string &name) :
800                 separateServiceObject(name) {}
801         };
802 
803         /**
804          * separate TCP and UDP services that match port ranges and
805          * "any tcp" or "any udp" objects
806          */
807         class separatePortRanges : public separateServiceObject
808         {
809             protected:
810             virtual bool condition(const libfwbuilder::Service *srv);
811             public:
separatePortRanges(const std::string & name)812             separatePortRanges(const std::string &name) :
813                 separateServiceObject(name) {}
814         };
815 
816 	/**
817 	 * verify if custom services used in rules are configured for
818 	 * this platform
819 	 */
820         class verifyCustomServices : public BasicRuleProcessor
821         {
822             public:
verifyCustomServices(const std::string & name)823             verifyCustomServices(const std::string &name) :
824                 BasicRuleProcessor(name) {}
825             virtual bool processNext();
826         };
827 
828 	/**
829 	 * simply check if TCPService object with "established" flag
830          * set is used in Service and abort with an error saying that
831          * target firewall does not support this. Use for pretty much
832          * every platform except ipfw and router ACLs
833 	 */
834         class CheckForTCPEstablished : public BasicRuleProcessor
835         {
836             public:
CheckForTCPEstablished(const std::string & name)837             CheckForTCPEstablished(const std::string &name) :
838                 BasicRuleProcessor(name) {}
839             virtual bool processNext();
840         };
841 
842 	/**
843 	 * simply check if UserService objectis used in Service and
844          * abort with an error saying that target firewall does not
845          * support this.
846 	 */
847         class CheckForUnsupportedUserService : public BasicRuleProcessor
848         {
849             public:
CheckForUnsupportedUserService(const std::string & name)850             CheckForUnsupportedUserService(const std::string &name) :
851                 BasicRuleProcessor(name) {}
852             virtual bool processNext();
853         };
854 
855         /**
856          * This rule processor replaces firewall object with
857          * DNSName object "self" configured as run-time with source
858          * name "self".
859          */
860         class ReplaceFirewallObjectWithSelfInRE : public BasicRuleProcessor
861         {
862             std::string re_type;
863             public:
ReplaceFirewallObjectWithSelfInRE(const std::string & n,std::string _type)864                 ReplaceFirewallObjectWithSelfInRE(const std::string &n,
865                                       std::string _type) :
866                 BasicRuleProcessor(n) { re_type=_type; }
867             virtual bool processNext();
868         };
869 
870         class RegisterGroupsAndTablesInRE : public BasicRuleProcessor
871         {
872             std::string re_type;
873             public:
RegisterGroupsAndTablesInRE(const std::string & n,const std::string _type)874                 RegisterGroupsAndTablesInRE(const std::string &n,
875                                             const std::string _type) :
876                 BasicRuleProcessor(n) { re_type = _type; }
877             virtual bool processNext();
878         };
879         friend class Compiler::RegisterGroupsAndTablesInRE;
880 
881         /**
882          * prints rule in some universal format (close to that visible
883          * to user in the GUI). Used for debugging purposes
884          */
885         virtual std::string debugPrintRule(libfwbuilder::Rule *rule);
886 
887         /**
888          * returns cached firewall object ID
889          */
getFwId()890         int getFwId() { return fw_id; }
891 
892         /**
893          * returns pointer to the cached firewall options object
894          */
getCachedFwOpt()895         libfwbuilder::FWOptions* getCachedFwOpt() { return fwopt; }
896 
897 	/**
898 	 * internal: scans children of 's' and, if finds host or
899 	 * firewall with multiple interfaces, replaces reference to
900 	 * that host or firewall with a set of references to its
901 	 * interfaces. Argument 's' should be a pointer at either src
902 	 * or dst in the rule. Some platforms may require alterations
903 	 * to * this algorithm, that's why it is virtual.
904 	 */
905 	virtual void _expand_addr(libfwbuilder::Rule *rule,
906                                   libfwbuilder::FWObject *s,
907                                   bool expand_cluster_interfaces_fully);
908 
909         /**
910          * internal: scans child objects of interface iface, both IPv4
911          * and physAddress, and puts them in the list ol. Policy
912          * compilers for platforms that support matching on MAC
913          * address should reimplement this method and do whatever is
914          * right for them (e.g. create combined address objects to
915          * fuse information from IPv4 and physAddress together).
916          *
917          * Parameter @expand_cluster_interfaces_fully is used when
918          * interface @iface belogns to a cluster and is failover
919          * interface. If @expand_cluster_interfaces_fully is true,
920          * this function scans failover group associated with this
921          * interface and takes address of the member firewall for
922          * which the policy is being compiled. If the cluster
923          * interface belongs to a cluster that is not being compiled,
924          * addresses of all members are returned instead. The address
925          * of the cluster interface is always returned even when
926          * @expand_cluster_interfaces_fully is false.
927          */
928         virtual void _expand_interface(libfwbuilder::Rule *rule,
929                                        libfwbuilder::Interface *iface,
930                                        std::list<libfwbuilder::FWObject*> &ol,
931                                        bool expand_cluster_interfaces_fully);
932 
933 	/**
934 	 * internal: like _expand_addr, but expands address range
935 	 * objects
936 	 */
937 	void _expandAddressRanges(libfwbuilder::Rule *rule,
938                                   libfwbuilder::FWObject *s);
939 
940 	/*
941 	 * normalizes port range (makes sure that niether range start
942 	 * nor end is <0 and so on
943 	 */
944 	void normalizePortRange(int &rs,int &re);
945 
946 
947         /**
948          * This method returns true if one of the following conditions is met:
949          *
950          * 1. obj1 is the same as obj2 (compares ID of both objects), or
951          * 2. obj1 is a child of obj2 on any depth, or
952          * 3. address of obj1 matches that of any obj2's interfaces, or
953          * 4. address of obj1 is a broadcast address of one of
954          *    the interfaces of obj2
955          * 5. address of obj1 is a broadcast (255.255.255.255)
956          */
957         bool complexMatch(libfwbuilder::Address *obj1,
958                           libfwbuilder::Address *obj2,
959                           bool recognize_broadcasts=true,
960                           bool recognize_multicasts=true);
961 
962         libfwbuilder::Address* correctForCluster(libfwbuilder::Address *adr);
963 
964         /**
965          * Compares given object with firewall or its parent cluster
966          * (if any).  Compares only IDs of these objects. Relies on
967          * class CompilerDriver to set integer variable
968          * "parent_cluster_id" in the firewall object if it is a
969          * member of a cluster.
970          */
971         bool isFirewallOrCluster(libfwbuilder::FWObject *obj);
972 
973         /**
974          * This method finds interface of obj2 (which is usually
975          * firewall object, but not necessarily so) which is connected
976          * to the subnet on which obj1 is located. It also works if
977          * obj1 is a network object, in this case it looks for the
978          * interface that belongs to that network.
979          */
980         libfwbuilder::Interface* findInterfaceFor(
981             const libfwbuilder::Address *o1, const libfwbuilder::Address *o2);
982 
983         /**
984          * This method finds an interface of the firewall obj2 which
985          * belongs to the subnet on which obj1 is located and returns
986          * IPv4 address object of this interface. It also works if
987          * obj1 is a network object, in this case it looks for the
988          * interface that belongs to that network.
989          *
990          * If obj1 is an Interface object, then corresponding Interface
991          * object belonging to the firewall is returned (if found).
992          */
993         libfwbuilder::FWObject* findAddressFor(
994             const libfwbuilder::Address *o1, const libfwbuilder::Address *o2);
995 
996 	virtual ~Compiler();
997 
998 	Compiler(libfwbuilder::FWObjectDatabase *_db,
999 		 libfwbuilder::Firewall *fw, bool ipv6_policy);
1000 
1001 	Compiler(libfwbuilder::FWObjectDatabase *_db,
1002 		 libfwbuilder::Firewall *fw, bool ipv6_policy,
1003 		 fwcompiler::OSConfigurator *_oscnf);
1004 /*
1005  * TODO: Refactor Compiler to not hide BaseCompiler
1006  */
1007 #pragma GCC diagnostic push
1008 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
1009 	Compiler(libfwbuilder::FWObjectDatabase *_db, bool ipv6_policy);
1010 
1011         /**
1012          * overloaded methods: uses current firewall and ruleset objects
1013          */
1014         virtual void abort(const std::string &errstr) throw(libfwbuilder::FWException);
1015         virtual void abort(libfwbuilder::FWObject *rule, const std::string &errstr)
1016             throw(libfwbuilder::FWException);
1017 
1018         virtual void error(const std::string &errstr);
1019         virtual void error(libfwbuilder::FWObject *rule, const std::string &errstr);
1020 
1021         virtual void warning(const std::string &errstr);
1022         virtual void warning(libfwbuilder::FWObject *rule, const std::string &errstr);
1023 #pragma GCC diagnostic pop
1024 
setDebugLevel(int dl)1025 	void setDebugLevel(int dl) { debug=dl;       }
setDebugRule(int dr)1026 	void setDebugRule(int dr)  { debug_rule = dr; rule_debug_on = true; }
setVerbose(bool v)1027 	void setVerbose(bool v)    { verbose=v;      }
1028         void setSingleRuleCompileMode(const std::string &rule_id);
inSingleRuleCompileMode()1029         bool inSingleRuleCompileMode() { return single_rule_mode; }
1030 
1031         void setSourceRuleSet(libfwbuilder::RuleSet *rs);
getSourceRuleSet()1032         libfwbuilder::RuleSet* getSourceRuleSet() { return source_ruleset; }
1033 
setRuleSetName(const std::string & name)1034         void setRuleSetName(const std::string &name) { ruleSetName = name; }
getRuleSetName()1035         std::string getRuleSetName() { return ruleSetName; }
1036 
1037         void setPersistentObjects(libfwbuilder::Library* po);
1038 
1039 	std::string getCompiledScript();
1040         int getCompiledScriptLength();
1041 
setGroupRegistry(GroupRegistry * gr)1042         void setGroupRegistry(GroupRegistry *gr) { group_registry = gr; }
1043 
1044         void expandGroup(libfwbuilder::FWObject *grp,
1045                          std::list<libfwbuilder::FWObject*> &ol);
1046 
1047 	void expandGroupsInRuleElement(libfwbuilder::RuleElement *s);
1048 
1049         /**
1050 	 * this method should return platform name. It is used
1051 	 * to construct proper error and warning messages.
1052 	 */
myPlatformName()1053 	virtual std::string myPlatformName() { return ""; }
1054 
1055 	std::string getUniqueRuleLabel();
1056 
1057 	virtual std::string createRuleLabel(const std::string &prefix,
1058                                             const std::string &txt,
1059                                             int rule_num);
1060         virtual std::string printComment(libfwbuilder::Rule *rule,
1061                                          std::string &prev_rule_label,
1062                                          const std::string &prefix,
1063                                          bool suppress_comment=false);
1064 
1065 	/**
1066 	 * prolog return number of rules found
1067 	 */
1068 	virtual int  prolog();
1069 	virtual void compile();
1070 	virtual void epilog();
1071 
1072 	/**
1073 	 * prints rule marked for debugging (its number * is in
1074 	 * debug_rule member variable)
1075 	 */
1076         void debugRule();
1077 
1078     };
1079 }
1080 
1081 #endif
1082