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