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