ÿØÿà JFIF    ÿÛ „  ( %"1!%)+...383,7(-.+  -+++--++++---+-+-----+---------------+---+-++7-----ÿÀ  ß â" ÿÄ     ÿÄ H    !1AQaq"‘¡2B±ÁÑð#R“Ò Tbr‚²á3csƒ’ÂñDS¢³$CÿÄ   ÿÄ %  !1AQa"23‘ÿÚ   ? ôÿ ¨pŸªáÿ —åYõõ\?àÒü©ŠÄï¨pŸªáÿ —åYõõ\?àÓü©ŠÄá 0Ÿªáÿ Ÿå[úƒ ú®ði~TÁbqÐ8OÕpÿ ƒOò¤Oè`–RÂáœá™êi€ßÉ< FtŸI“öÌ8úDf´°å}“¾œ6  öFá°y¥jñÇh†ˆ¢ã/ÃÐ:ªcÈ "Y¡ðÑl>ÿ ”ÏËte:qž\oäŠe÷󲍷˜HT4&ÿ ÓÐü6ö®¿øþßèô Ÿ•7Ñi’•j|“ñì>b…þS?*Óôÿ ÓÐü*h¥£ír¶ü UãS炟[AÐaè[ûª•õ&õj?†Éö+EzP—WeÒírJFt ‘BŒ†Ï‡%#tE Øz ¥OÛ«!1›üä±Í™%ºÍãö]°î(–:@<‹ŒÊö×òÆt¦ãº+‡¦%ÌÁ²h´OƒJŒtMÜ>ÀÜÊw3Y´•牋4ǍýʏTì>œú=Íwhyë,¾Ôò×õ¿ßÊa»«þˆѪQ|%6ž™A õ%:øj<>É—ÿ Å_ˆCbõ¥š±ý¯Ýƒï…¶|RëócÍf溪“t.СøTÿ *Ä¿-{†çàczůŽ_–^XþŒ±miB[X±d 1,é”zEù»& î9gœf™9Ð'.;—™i}!ôšåîqêÛ٤ёý£½ÆA–àôe"A$˝Úsäÿ ÷Û #°xŸëí(l »ý3—¥5m! rt`†0~'j2(]S¦¦kv,ÚÇ l¦øJA£Šƒ J3E8ÙiŽ:cÉžúeZ°€¯\®kÖ(79«Ž:¯X”¾³Š&¡* ….‰Ž(ÜíŸ2¥ª‡×Hi²TF¤ò[¨íÈRëÉ䢍mgÑ.Ÿ<öäS0í„ǹÁU´f#Vß;Õ–…P@3ío<ä-±»Ž.L|kªÀê›fÂ6@»eu‚|ÓaÞÆŸ…¨ááå>åŠ?cKü6ùTÍÆ”†sĤÚ;H2RÚ†õ\Ö·Ÿn'¾ ñ#ºI¤Å´%çÁ­‚â7›‹qT3Iï¨ÖÚ5I7Ë!ÅOóŸ¶øÝñØôת¦$Tcö‘[«Ö³šÒ';Aþ ¸èíg A2Z"i¸vdÄ÷.iõ®§)¿]¤À†–‡É&ä{V¶iŽ”.Ó×Õÿ û?h¬Mt–íª[ÿ Ñÿ ÌV(í}=ibÔ¡›¥¢±b Lô¥‡piη_Z<‡z§èŒ)iÖwiÇ 2hÙ3·=’d÷8éŽ1¦¸c¤µ€7›7Ø ð\á)} ¹fËí›pAÃL%âc2 í§æQz¿;T8sæ°qø)QFMð‰XŒÂ±N¢aF¨…8¯!U  Z©RÊ ÖPVÄÀÍin™Ì-GˆªÅËŠ›•zË}º±ŽÍFò¹}Uw×#ä5B¤{î}Ð<ÙD é©¤&‡ïDbàÁôMÁ." ¤‡ú*õ'VŽ|¼´Úgllº¼klz[Æüï÷Aób‡Eÿ dÑ»Xx9ÃÜ£ÁT/`¼¸vI±Ýµ·Ë‚“G³þ*Ÿû´r|*}<¨îºœ @¦mÄ’M¹”.œ«Y–|6ÏU¤jç¥ÕÞqO ˜kDÆÁ¨5ÿ š;ÐЦ¦€GÙk \ –Þ=â¼=SͧµªS°ÚÍpÜãQűÀõ¬?ÃÁ1Ñ•õZà?hóœ€ L¦l{Y*K˜Ù›zc˜–ˆâ ø+¾ ­-Ök¥%ùEÜA'}ˆ><ÊIè“bpÍ/qÞâvoX€w,\úªò6Z[XdÒæ­@Ö—€$òJí#é>'°Ú ôª˜<)4ryÙ£|óAÅn5žêŸyÒäMÝ2{"}‰–¤l÷ûWX\l¾Á¸góÉOÔ /óñB¤f¸çñ[.P˜ZsÊË*ßT܈§QN¢’¡¨§V¼(Üù*eÕ“”5T¨‹Âê¥FŒã½Dü[8'Ò¥a…Ú¶k7a *•›¼'Ò·\8¨ª\@\õ¢¦íq+DÙrmÎ…_ªæ»ŠÓœ¡¯’Ré9MÅ×D™lælffc+ŒÑ,ý™ÿ ¯þǤ=Å’Á7µ÷ÚÛ/“Ü€ñýã¼àí¾ÕÑ+ƒ,uµMâÀÄbm:ÒÎPæ{˜Gz[ƒ¯«® KHà`ߨŠéí¯P8Aq.C‰ à€kòpj´kN¶qô€…Õ,ÜNŠª-­{Zö’æû44‰sŽè‰îVíRœÕm" 6?³D9¡ÇTíÅꋇ`4«¸ÝÁô ï’ýorqКÇZ«x4Žâéþuïf¹µö[P ,Q£éaX±`PÉÍZ ¸äYúg üAx ’6Lê‚xÝÓ*äQ  Ï’¨hÍ =²,6ï#rÃ<¯–£»ƒ‹,–ê•€ aÛsñ'%Æ"®ÛüìBᝠHÚ3ß°©$“XnœÖ’î2ËTeûìxîß ¦å¿çÉ ðK§þ{‘t‚Ϋ¬jéîZ[ ”š7L¥4VÚCE×]m¤Øy”ä4-dz£œ§¸x.*ãÊÊ b÷•h:©‡¦s`BTÁRû¾g⻩‹jø sF¢àJøFl‘È•Xᓁà~*j¯ +(ÚÕ6-£¯÷GŠØy‚<Ç’.F‹Hœw(+)ÜÜâÈzÄäT§FߘãÏ;DmVœ3Àu@mÚüXÝü•3B¨òÌÁÛ<·ÃÜ z,Ì@õÅ·d2]ü8s÷IôÞ¯^Ç9¢u„~ëAŸï4«M? K]­ÅàPl@s_ p:°¬ZR”´›JC[CS.h‹ƒïËœ«Æ]–÷ó‚wR×k7X‰k›‘´ù¦=¡«‰¨¨Â')—71ó’c‡Ðúµ `é.{§p¹ój\Ž{1h{o±Ý=áUÊïGÖŒõ–-BÄm+AZX¶¡ ïHðæ¥JmÙ;…䡟ˆ¦ ° äšiÉg«$üMk5¤L“’çÊvïâï ,=f“"íἊ5ô¬x6{ɏžID0e¸vçmi'︧ºð9$ò¹÷*£’9ÿ ²TÔ…×>JV¥}Œ}$p[bÔ®*[jzS*8 ”·T›Í–ñUîƒwo$áè=LT™ç—~ô·¤ÈÚ$榍q‰„+´kFm)ž‹©i–ËqÞŠ‰à¶ü( ‚•§ •°ò·‡#5ª•µÊ﯅¡X¨šÁ*F#TXJÊ ušJVÍ&=iÄs1‚3•'fý§5Ñ<=[íÞ­ PÚ;ѱÌ_~Ä££8rÞ ²w;’hDT°>ÈG¬8Á²ÚzŽ®ò®qZcqJêäÞ-ö[ܘbň±çb“ж31²n×iƒðÕ;1¶þÉ ªX‰,ßqÏ$>•î íZ¥Z 1{ç൵+ƒÕµ¥°T$§K]á»Ûï*·¤tMI’ÂZbŽÕiÒ˜}bÓ0£ª5›¨ [5Ž^ÝœWøÂÝh° ¢OWun£¤5 a2Z.G2³YL]jåtì”ä ÁÓ‘%"©<Ôúʰsº UZvä‡ÄiÆÒM .÷V·™ø#kèýiíÌ–ª)µT[)BˆõÑ xB¾B€ÖT¨.¥~ð@VĶr#¸ü*åZNDŽH;âi ],©£öØpù(šºãö¼T.uCê•4@ÿ GÕÛ)Cx›®0ø#:ÏðFÒbR\(€€Ä®fã4Þ‰Fä¯HXƒÅ,†öEÑÔÜ]Öv²?tLÃvBY£ú6Êu5ÅAQ³1‘’¬x–HŒÐ‡ ^ ¸KwJôÖŽ5×CÚ¨vÜ«/B0$×k°=ðbÇ(Ï)w±A†Á† 11Í=èQšµ626ŒÜ/`G«µ<}—-Ö7KEHÈÉðóȤmݱû±·ø«Snmá=“䫚mݱŸ¡¶~ó·“äUóJæúòB|E LêŽy´jDÔ$G¢þÐñ7óR8ýÒ…Ç› WVe#·Ÿ p·Fx~•ݤF÷0Èÿ K¯æS<6’¡WШ; ´ÿ ¥Êø\Òuî†åÝ–VNœkÒ7oòX¨Á­Ø÷FÎÑä±g÷ÿ M~Çî=p,X´ ÝÌÚÅ‹’ÃjÖ.ØöÏñ qïQ¤ÓZE†° =6·]܈ s¸>v•Ž^Ý\wq9r‰Î\¸¡kURÒ$­*‹Nq?Þª*!sŠÆ:TU_u±T+øX¡ ®¹¡,ÄâÃBTsÜ$Ø›4m椴zÜK]’’›Pƒ @€#â˜`é¹=I‡fiV•Ôî“nRm+µFPOhÍ0B£ €+¬5c v•:P'ÒyÎ ‰V~‚Ó†ÖuókDoh$å\*ö%Ю=£«…aȼ½÷Û.-½VŒŠ¼'lyî±1¬3ó#ÞE¿ÔS¤gV£m›=§\û"—WU¤ÚǼÿ ÂnÁGŒÃ ‚õN D³õNÚíŒÕ;HôyÄÈ©P¹Ä{:?R‘Ô¨âF÷ø£bÅó® JS|‚R÷ivýáâ€Æé¡è³´IئÑT!§˜•ت‚¬â@q€wnïCWÄ@JU€ê¯m6]Ï:£âx'+ÒðXvÓ¦Úm=–´7œ $ì“B£~p%ÕŸUþ« N@¼üï~w˜ñø5®—'Ôe»¤5ã//€ž~‰Tþ›Å7•#¤× Íö pÄ$ùeåì*«ÓŠEØWEÈsßg ¦ûvžSsLpºÊW–âµEWöˬH; ™!CYõZ ÃÄf æ#1W. \uWâ\,\Çf j’<qTbên›Î[vxx£ë 'ö¨1›˜ÀM¼Pÿ H)ƒêêŒA7s,|F“ 꺸k³9Ìö*ç®;Ö!Ö$Eiž•¹ÒÚ†ýóéÝû¾ÕS®ó$’NÝäŸz¤5r¦ãÄÃD÷Üø!°ø‡Ô&@m™Ì^Ãä­d q5Lnÿ N;.6½·N|#ä"1Nƒx“ã<3('&ñßt  ~ªu”1Tb㫨9ê–›–bìd$ߣ=#ÕãÒmU¯eí$EFù5ýYô櫨æì™Ç—±ssM]·á¿0ÕåJRÓªîiƒ+O58ÖñªŠÒx" \µâá¨i’¤i —Ö ” M+M¤ë9‚‰A¦°Qõ¾ßøK~¼Ã‘g…Ö´~÷Ï[3GUœÒ½#…kàÔ®Ò”‰³·dWV‰IP‰Ú8u¹”E ÖqLj¾êÕCBš{A^Âß;–¨`¯¬ìö ˼ ×tìø.tƐm*n¨y4o&Àx¥n¦×î‡aupáÛj8¿m›è¶ã!o½;ß0y^ý×^EÑ¿ÒjzŒ­)vÚÑnÄL …^ªô× ‡—‚3k Îý­hï]içå–îÏ*÷ñþ»Ô CÒjøjÍznˆ´ ¹#b'Fô‹ ‰v¥'’à'T´ƒHýÍ%M‰ ƒ&ÆÇŒï1 ‘ –Þ ‰i¬s žR-Ÿ kЬá¬7:þ 0ŒÅÒÕ/aÙ¬ÃÝ#Úøœ ©aiVc‰. ¹¦ãµ” ›Yg¦›ÆÎýº°f³7ƒhá·¸­}&D9¡ÂsÉÙÞèŠõØàC™¨ñbFC|´Ü(ŸƒÚÒ-%»'a Ì¿)ËÇn¿úÿ ÞŽX…4ÊÅH^ôΑí@ù¹Eh¶“L8Çjù ¼ÎåVªóR©Ï5uà V4lZß®=€xÖŸ–ÑÈ ÷”¨°¾__yM1tÉ?uÆþIkÄgæ@þ[¢†°XÃJ£j·:nkÅ¢u ‘}âGzö­/IµèЬ¼48q¦F°ŽR¼=ûì{´¯RýicS ÕÛ íNtÍÙï£,w4rêì®»~x(©Uñ§#Ñ&œÕ¤>ÎåÍÓ9’Ö{9eV­[Öjâ²ãu]˜å2›qÑšÕJç0€sÄ|Êëè0튔bÁ>“{×_F`Ø©ºê:µä,v¤ðfc1±"«ÔÍän1#=· Âøv~H½ÐßA¾¿Ü€Óš]Õ; I¾÷ç‚Qi†î¹9ywÔKG˜áñ zQY—§ÃÕZ07§X‚ Áh;ÁM)iÌCH-¯T‘ë|A0{Ò½LÚ–TâÖkÜ’dÀ“rmm»”جPF³ÖcbE§T€ÒxKºû’Ó®7±²(\4ŽÃ¸Uu@j™yĵ;³µ!Á¢b.W¤=mõ´êµK k ¸K^ÜÛ#p*Ü14qkZç5ïë †°5Ï%ÍÛ<Õ¤×Ô¥ê†C Õ´¼ú$ƒÖ“”]Ù¬qÞÚ[4©ý!ûÏ—Áb쳐XµA¬â~`›Çr¸8ìùÝ䫦<>ä÷«?xs´ÇÑ /á;¹øüÊÈÙà{"@Žïzâ¬[âß‚ U_<ÇŸ½4èN˜ú61®qŠu ¦þF£»äJ_ˆÙÎ~ ÞAã–݄ϗrŠD;xTž‘ô`É«…suãO`?³à™ô Lý#Íc5öoæØ‚y´´÷«ZR§<&JÇ+éâô´€i!Àˆ0æAoàðLèÖ-2ŸõW.’t^–(KÁmHµV@xÜÇy®Ñø­â^:Ú3w· 7½¹°ñ¸â¹®:',«Mœ—n­Á+Ãbš LÈ‘ÄnRÓÅœ%¦²‰¨ùQ:¤f‚ "PÕtô¸…cæl…&˜Ú˜Ôkv‹ž+vŠ,=¢v­6—Xy*¥t£«<™:“aîϲ=¦6rO]XI¿Œ÷¤zÚ­›¶ 6÷”w\d ü~v®ˆÌk«^m<ÿ ¢‰Õ\)ùºŽ;… lîÙÅEŠ®cѾ@vnMÏ,¼“ñ•ŽBxðÃzãÇç%3ˆ"}Ù•Åî> BÉú;Ò]V+P˜F_´ßé> Øše|ï‡ÄOmFæÇ ãqÞ$/xÐx­z`ï9"œÜij‚!7.\Td…9M‡•iŽ‹¾‘50ÞŽn¥ß4ÉôO ¹*í^QêËÜÇÌ8=ާs‰'ÂëÙ«á%Pú[O †ÅP¯Vsް.‰,kc¶ ¬A9n˜XÎ-ÞšN["¹QÕ‰ƒMýÁߺXJæÍaLj¾×Ãmã¾ãÚ uñÒþåQô¦¥ /ÄUx:‚ÍÜ’ Đ©ØÝ3V¨‰ÕnÐ6ó*óúK­«…c ¯U òhsý­jóÔj#,ímŒRµ«lbïUTŒÑ8†Ä0œÏr`ð¡¬É Ї ë"À² ™ 6¥ f¶ ¢ÚoܱԷ-<Àî)†a¶ž'Ú»¨TXqØæ¶÷YÄHy˜9ÈIW­YÀuMFë ºÏ’AqÌ4·/Ú †ô'i$øä­=Ä Ý|öK×40è|È6p‘0§)o¥ctî§H+CA-“ xØ|ÐXАç l8íºð3Ø:³¤¬KX¯UÿÙ # -*- coding: utf-8 -*- # # Copyright (C) 2011-2016 Red Hat, Inc. # # Authors: # Thomas Woerner # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # import time import copy from firewall.core.base import SHORTCUTS, DEFAULT_ZONE_TARGET, SOURCE_IPSET_TYPES from firewall.core.fw_transaction import FirewallTransaction from firewall.core.io.policy import Policy from firewall.core.logger import log from firewall.core.rich import Rich_Service, Rich_Port, Rich_Protocol, Rich_SourcePort, Rich_ForwardPort, \ Rich_IcmpBlock, Rich_IcmpType, Rich_Masquerade, Rich_Mark from firewall.functions import checkIPnMask, checkIP6nMask, check_mac from firewall import errors from firewall.errors import FirewallError from firewall.fw_types import LastUpdatedOrderedDict class FirewallZone(object): ZONE_POLICY_PRIORITY = 0 def __init__(self, fw): self._fw = fw self._zones = { } self._zone_policies = { } def __repr__(self): return '%s(%r)' % (self.__class__, self._zones) def cleanup(self): self._zones.clear() self._zone_policies.clear() def new_transaction(self): return FirewallTransaction(self._fw) def policy_name_from_zones(self, fromZone, toZone): return "zone_{fromZone}_{toZone}".format(fromZone=fromZone, toZone=toZone) # zones def get_zones(self): return sorted(self._zones.keys()) def get_active_zones(self): active_zones = [] for zone in self.get_zones(): if self.list_interfaces(zone) or self.list_sources(zone): active_zones.append(zone) return active_zones def get_zone_of_interface(self, interface): interface_id = self.__interface_id(interface) for zone in self._zones: if interface_id in self._zones[zone].settings["interfaces"]: # an interface can only be part of one zone return zone return None def get_zone_of_source(self, source): source_id = self.__source_id(source) for zone in self._zones: if source_id in self._zones[zone].settings["sources"]: # a source_id can only be part of one zone return zone return None def get_zone(self, zone): z = self._fw.check_zone(zone) return self._zones[z] def policy_obj_from_zone_obj(self, z_obj, fromZone, toZone): p_obj = Policy() p_obj.derived_from_zone = z_obj.name p_obj.name = self.policy_name_from_zones(fromZone, toZone) p_obj.priority = self.ZONE_POLICY_PRIORITY p_obj.target = z_obj.target p_obj.ingress_zones = [fromZone] p_obj.egress_zones = [toZone] # copy zone permanent config to policy permanent config # WARN: This assumes the same attribute names. # for setting in ["services", "ports", "masquerade", "forward_ports", "source_ports", "icmp_blocks", "rules", "protocols"]: if fromZone == z_obj.name and toZone == "HOST" and \ setting in ["services", "ports", "source_ports", "icmp_blocks", "protocols"]: # zone --> HOST setattr(p_obj, setting, copy.deepcopy(getattr(z_obj, setting))) elif fromZone == "ANY" and toZone == z_obj.name and setting in ["masquerade"]: # any zone --> zone setattr(p_obj, setting, copy.deepcopy(getattr(z_obj, setting))) elif fromZone == z_obj.name and toZone == "ANY" and \ setting in ["icmp_blocks", "forward_ports"]: # zone --> any zone setattr(p_obj, setting, copy.deepcopy(getattr(z_obj, setting))) elif setting in ["rules"]: p_obj.rules = [] for rule in z_obj.rules: current_policy = self.policy_name_from_zones(fromZone, toZone) if current_policy in self._rich_rule_to_policies(z_obj.name, rule): p_obj.rules.append(copy.deepcopy(rule)) return p_obj def add_zone(self, obj): obj.settings = { x : LastUpdatedOrderedDict() for x in ["interfaces", "sources", "icmp_block_inversion", "forward"] } self._zones[obj.name] = obj self._zone_policies[obj.name] = [] # Create policy objects, will need many: # - (zone --> HOST) - ports, service, etc # - (any zone --> zone) - masquerade # - (zone --> any zone) - ICMP block, icmp block inversion # - also includes forward-ports because it works on (nat, # PREROUTING) and therefore applies to redirects to the local # host or dnat to a different host. # - also includes rich rule "mark" action for the same reason # for fromZone,toZone in [(obj.name, "HOST"), ("ANY", obj.name), (obj.name, "ANY")]: p_obj = self.policy_obj_from_zone_obj(obj, fromZone, toZone) self._fw.policy.add_policy(p_obj) self._zone_policies[obj.name].append(p_obj.name) self.copy_permanent_to_runtime(obj.name) def copy_permanent_to_runtime(self, zone): obj = self._zones[zone] for arg in obj.interfaces: self.add_interface(zone, arg, allow_apply=False) for arg in obj.sources: self.add_source(zone, arg, allow_apply=False) if obj.forward: self.add_forward(zone) if obj.icmp_block_inversion: self.add_icmp_block_inversion(zone) def remove_zone(self, zone): obj = self._zones[zone] if obj.applied: self.unapply_zone_settings(zone) obj.settings.clear() del self._zones[zone] del self._zone_policies[zone] def apply_zones(self, use_transaction=None): for zone in self.get_zones(): z_obj = self._zones[zone] if len(z_obj.interfaces) > 0 or len(z_obj.sources) > 0: log.debug1("Applying zone '%s'", zone) self.apply_zone_settings(zone, use_transaction=use_transaction) def set_zone_applied(self, zone, applied): obj = self._zones[zone] obj.applied = applied # zone from chain def zone_from_chain(self, chain): if "_" not in chain: # no zone chain return None splits = chain.split("_") if len(splits) < 2: return None _chain = None for x in SHORTCUTS: if splits[0] == SHORTCUTS[x]: _chain = x if _chain is not None: # next part needs to be zone name if splits[1] not in self.get_zones(): return None if len(splits) == 2 or \ (len(splits) == 3 and splits[2] in [ "pre", "log", "deny", "allow", "post" ]): return (splits[1], _chain) return None def policy_from_chain(self, chain): x = self.zone_from_chain(chain) if x is None: return None (zone, _chain) = x # derived from _get_table_chains_for_zone_dispatch() if _chain in ["PREROUTING", "FORWARD_IN"]: fromZone = zone toZone = "ANY" elif _chain in ["INPUT"]: fromZone = zone toZone = "HOST" elif _chain in ["POSTROUTING", "FORWARD_OUT"]: fromZone = "ANY" toZone = zone else: raise FirewallError(errors.INVALID_CHAIN, "chain '%s' can't be mapped to a policy" % (chain)) return (self.policy_name_from_zones(fromZone, toZone), _chain) def create_zone_base_by_chain(self, ipv, table, chain, use_transaction=None): # Create zone base chains if the chain is reserved for a zone if ipv in [ "ipv4", "ipv6" ]: x = self.policy_from_chain(chain) if x is not None: (policy, _chain) = self.policy_from_chain(chain) if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction self._fw.policy.gen_chain_rules(policy, True, table, _chain, transaction) if use_transaction is None: transaction.execute(True) # settings # generate settings record with sender, timeout def __gen_settings(self, timeout, sender): ret = { "date": time.time(), "sender": sender, "timeout": timeout, } return ret def get_settings(self, zone): return self.get_zone(zone).settings def _zone_settings(self, enable, zone, transaction): settings = self.get_settings(zone) for key in settings: for args in settings[key]: if key == "interfaces": self._interface(enable, zone, args, transaction) elif key == "sources": self._source(enable, zone, args[0], args[1], transaction) elif key == "icmp_block_inversion": continue elif key == "forward": # no need to call this when applying the zone as the rules # will be generated when adding the interfaces/sources pass else: log.warning("Zone '%s': Unknown setting '%s:%s', " "unable to apply", zone, key, args) # ICMP-block-inversion is always applied if enable: self._icmp_block_inversion(enable, zone, transaction) def apply_zone_settings(self, zone, use_transaction=None): _zone = self._fw.check_zone(zone) obj = self._zones[_zone] if obj.applied: return obj.applied = True if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction for policy in self._zone_policies[_zone]: log.debug1("Applying policy (%s) derived from zone '%s'", policy, zone) self._fw.policy.apply_policy_settings(policy, use_transaction=transaction) self._zone_settings(True, _zone, transaction) if use_transaction is None: transaction.execute(True) def unapply_zone_settings(self, zone, use_transaction=None): _zone = self._fw.check_zone(zone) obj = self._zones[_zone] if not obj.applied: return if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction for policy in self._zone_policies[_zone]: self._fw.policy.unapply_policy_settings(policy, use_transaction=transaction) self._zone_settings(False, _zone, transaction) if use_transaction is None: transaction.execute(True) def get_config_with_settings(self, zone): """ :return: exported config updated with runtime settings """ obj = self.get_zone(zone) conf_dict = self.get_config_with_settings_dict(zone) conf_list = [] for i in range(16): # tuple based API has 16 elements if obj.IMPORT_EXPORT_STRUCTURE[i][0] not in conf_dict: # old API needs the empty elements as well. Grab it from the # class otherwise we don't know the type. conf_list.append(copy.deepcopy(getattr(obj, obj.IMPORT_EXPORT_STRUCTURE[i][0]))) else: conf_list.append(conf_dict[obj.IMPORT_EXPORT_STRUCTURE[i][0]]) return tuple(conf_list) def get_config_with_settings_dict(self, zone): """ :return: exported config updated with runtime settings """ permanent = self.get_zone(zone).export_config_dict() if permanent["target"] == DEFAULT_ZONE_TARGET: permanent["target"] = "default" runtime = { "services": self.list_services(zone), "ports": self.list_ports(zone), "icmp_blocks": self.list_icmp_blocks(zone), "masquerade": self.query_masquerade(zone), "forward_ports": self.list_forward_ports(zone), "interfaces": self.list_interfaces(zone), "sources": self.list_sources(zone), "rules_str": self.list_rules(zone), "protocols": self.list_protocols(zone), "source_ports": self.list_source_ports(zone), "icmp_block_inversion": self.query_icmp_block_inversion(zone), "forward": self.query_forward(zone), } return self._fw.combine_runtime_with_permanent_settings(permanent, runtime) def set_config_with_settings_dict(self, zone, settings, sender): # stupid wrappers to convert rich rule string to rich rule object from firewall.core.rich import Rich_Rule def add_rule_wrapper(zone, rule_str, timeout=0, sender=None): self.add_rule(zone, Rich_Rule(rule_str=rule_str), timeout=0, sender=sender) def remove_rule_wrapper(zone, rule_str): self.remove_rule(zone, Rich_Rule(rule_str=rule_str)) setting_to_fn = { "services": (self.add_service, self.remove_service), "ports": (self.add_port, self.remove_port), "icmp_blocks": (self.add_icmp_block, self.remove_icmp_block), "masquerade": (self.add_masquerade, self.remove_masquerade), "forward_ports": (self.add_forward_port, self.remove_forward_port), "interfaces": (self.add_interface, self.remove_interface), "sources": (self.add_source, self.remove_source), "rules_str": (add_rule_wrapper, remove_rule_wrapper), "protocols": (self.add_protocol, self.remove_protocol), "source_ports": (self.add_source_port, self.remove_source_port), "icmp_block_inversion": (self.add_icmp_block_inversion, self.remove_icmp_block_inversion), "forward": (self.add_forward, self.remove_forward), } old_settings = self.get_config_with_settings_dict(zone) (add_settings, remove_settings) = self._fw.get_added_and_removed_settings(old_settings, settings) for key in remove_settings: if isinstance(remove_settings[key], list): for args in remove_settings[key]: if isinstance(args, tuple): setting_to_fn[key][1](zone, *args) else: setting_to_fn[key][1](zone, args) else: # bool setting_to_fn[key][1](zone) for key in add_settings: if isinstance(add_settings[key], list): for args in add_settings[key]: if key in ["interfaces", "sources"]: # no timeout arg setting_to_fn[key][0](zone, args, sender=sender) else: if isinstance(args, tuple): setting_to_fn[key][0](zone, *args, timeout=0, sender=sender) else: setting_to_fn[key][0](zone, args, timeout=0, sender=sender) else: # bool if key in ["icmp_block_inversion"]: # no timeout arg setting_to_fn[key][0](zone, sender=sender) else: setting_to_fn[key][0](zone, timeout=0, sender=sender) # INTERFACES def check_interface(self, interface): self._fw.check_interface(interface) def interface_get_sender(self, zone, interface): _zone = self._fw.check_zone(zone) _obj = self._zones[_zone] interface_id = self.__interface_id(interface) if interface_id in _obj.settings["interfaces"]: settings = _obj.settings["interfaces"][interface_id] if "sender" in settings and settings["sender"] is not None: return settings["sender"] return None def __interface_id(self, interface): self.check_interface(interface) return interface def add_interface(self, zone, interface, sender=None, use_transaction=None, allow_apply=True): self._fw.check_panic() _zone = self._fw.check_zone(zone) _obj = self._zones[_zone] interface_id = self.__interface_id(interface) if interface_id in _obj.settings["interfaces"]: raise FirewallError(errors.ZONE_ALREADY_SET, "'%s' already bound to '%s'" % (interface, zone)) if self.get_zone_of_interface(interface) is not None: raise FirewallError(errors.ZONE_CONFLICT, "'%s' already bound to a zone" % interface) log.debug1("Setting zone of interface '%s' to '%s'" % (interface, _zone)) if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction if not _obj.applied and allow_apply: self.apply_zone_settings(zone, use_transaction=transaction) transaction.add_fail(self.set_zone_applied, _zone, False) if allow_apply: self._interface(True, _zone, interface, transaction) self.__register_interface(_obj, interface_id, zone, sender) transaction.add_fail(self.__unregister_interface, _obj, interface_id) if use_transaction is None: transaction.execute(True) return _zone def __register_interface(self, _obj, interface_id, zone, sender): _obj.settings["interfaces"][interface_id] = \ self.__gen_settings(0, sender) # add information whether we add to default or specific zone _obj.settings["interfaces"][interface_id]["__default__"] = \ (not zone or zone == "") def change_zone_of_interface(self, zone, interface, sender=None): self._fw.check_panic() _old_zone = self.get_zone_of_interface(interface) _new_zone = self._fw.check_zone(zone) if _new_zone == _old_zone: return _old_zone if _old_zone is not None: self.remove_interface(_old_zone, interface) _zone = self.add_interface(zone, interface, sender) return _zone def change_default_zone(self, old_zone, new_zone, use_transaction=None): self._fw.check_panic() if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction self.apply_zone_settings(new_zone, transaction) self._interface(True, new_zone, "+", transaction, append=True) if old_zone is not None and old_zone != "": self._interface(False, old_zone, "+", transaction, append=True) if use_transaction is None: transaction.execute(True) def remove_interface(self, zone, interface, use_transaction=None): self._fw.check_panic() zoi = self.get_zone_of_interface(interface) if zoi is None: raise FirewallError(errors.UNKNOWN_INTERFACE, "'%s' is not in any zone" % interface) _zone = zoi if zone == "" else self._fw.check_zone(zone) if zoi != _zone: raise FirewallError(errors.ZONE_CONFLICT, "remove_interface(%s, %s): zoi='%s'" % \ (zone, interface, zoi)) if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction _obj = self._zones[_zone] interface_id = self.__interface_id(interface) transaction.add_post(self.__unregister_interface, _obj, interface_id) self._interface(False, _zone, interface, transaction) if use_transaction is None: transaction.execute(True) return _zone def __unregister_interface(self, _obj, interface_id): if interface_id in _obj.settings["interfaces"]: del _obj.settings["interfaces"][interface_id] def query_interface(self, zone, interface): return self.__interface_id(interface) in self.get_settings(zone)["interfaces"] def list_interfaces(self, zone): return self.get_settings(zone)["interfaces"].keys() # SOURCES def check_source(self, source, applied=False): if checkIPnMask(source): return "ipv4" elif checkIP6nMask(source): return "ipv6" elif check_mac(source): return "" elif source.startswith("ipset:"): self._check_ipset_type_for_source(source[6:]) if applied: self._check_ipset_applied(source[6:]) return self._ipset_family(source[6:]) else: raise FirewallError(errors.INVALID_ADDR, source) def __source_id(self, source, applied=False): ipv = self.check_source(source, applied=applied) return (ipv, source) def add_source(self, zone, source, sender=None, use_transaction=None, allow_apply=True): self._fw.check_panic() _zone = self._fw.check_zone(zone) _obj = self._zones[_zone] if check_mac(source): source = source.upper() source_id = self.__source_id(source, applied=allow_apply) if source_id in _obj.settings["sources"]: raise FirewallError(errors.ZONE_ALREADY_SET, "'%s' already bound to '%s'" % (source, _zone)) if self.get_zone_of_source(source) is not None: raise FirewallError(errors.ZONE_CONFLICT, "'%s' already bound to a zone" % source) if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction if not _obj.applied and allow_apply: self.apply_zone_settings(zone, use_transaction=transaction) transaction.add_fail(self.set_zone_applied, _zone, False) if allow_apply: self._source(True, _zone, source_id[0], source_id[1], transaction) self.__register_source(_obj, source_id, zone, sender) transaction.add_fail(self.__unregister_source, _obj, source_id) if use_transaction is None: transaction.execute(True) return _zone def __register_source(self, _obj, source_id, zone, sender): _obj.settings["sources"][source_id] = \ self.__gen_settings(0, sender) # add information whether we add to default or specific zone _obj.settings["sources"][source_id]["__default__"] = (not zone or zone == "") def change_zone_of_source(self, zone, source, sender=None): self._fw.check_panic() _old_zone = self.get_zone_of_source(source) _new_zone = self._fw.check_zone(zone) if _new_zone == _old_zone: return _old_zone if check_mac(source): source = source.upper() if _old_zone is not None: self.remove_source(_old_zone, source) _zone = self.add_source(zone, source, sender) return _zone def remove_source(self, zone, source, use_transaction=None): self._fw.check_panic() if check_mac(source): source = source.upper() zos = self.get_zone_of_source(source) if zos is None: raise FirewallError(errors.UNKNOWN_SOURCE, "'%s' is not in any zone" % source) _zone = zos if zone == "" else self._fw.check_zone(zone) if zos != _zone: raise FirewallError(errors.ZONE_CONFLICT, "remove_source(%s, %s): zos='%s'" % \ (zone, source, zos)) if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction _obj = self._zones[_zone] source_id = self.__source_id(source) transaction.add_post(self.__unregister_source, _obj, source_id) self._source(False, _zone, source_id[0], source_id[1], transaction) if use_transaction is None: transaction.execute(True) return _zone def __unregister_source(self, _obj, source_id): if source_id in _obj.settings["sources"]: del _obj.settings["sources"][source_id] def query_source(self, zone, source): if check_mac(source): source = source.upper() return self.__source_id(source) in self.get_settings(zone)["sources"] def list_sources(self, zone): return [ k[1] for k in self.get_settings(zone)["sources"].keys() ] def _interface(self, enable, zone, interface, transaction, append=False): for backend in self._fw.enabled_backends(): if not backend.policies_supported: continue for policy in self._zone_policies[zone]: for (table, chain) in self._fw.policy._get_table_chains_for_zone_dispatch(policy): rules = backend.build_zone_source_interface_rules(enable, zone, policy, interface, table, chain, append) transaction.add_rules(backend, rules) # intra zone forward policy = self.policy_name_from_zones(zone, "ANY") # Skip adding wildcard/catch-all interface (for default # zone). Otherwise it would allow forwarding from interface # in default zone -> interface not in default zone (but in # a different zone). if self.get_settings(zone)["forward"] and interface not in ["+", "*"]: rules = backend.build_zone_forward_rules(enable, zone, policy, "filter", interface=interface) transaction.add_rules(backend, rules) # update policy dispatch for any policy using this zone in ingress # or egress for policy in self._fw.policy.get_policies_not_derived_from_zone(): if zone not in self._fw.policy.list_ingress_zones(policy) and \ zone not in self._fw.policy.list_egress_zones(policy): continue if policy in self._fw.policy.get_active_policies_not_derived_from_zone() and self._fw.policy.get_policy(policy).applied: # first remove the old set of interfaces using the current zone # settings. if not enable and len(self.list_interfaces(zone)) == 1: self._fw.policy.unapply_policy_settings(policy, use_transaction=transaction) else: self._fw.policy._ingress_egress_zones(False, policy, transaction) # after the transaction ends and therefore the interface # has been added to the zone's settings, update the # dependent policies transaction.add_post(lambda p: (p in self._fw.policy.get_active_policies_not_derived_from_zone()) and \ self._fw.policy._ingress_egress_zones_transaction(True, p), policy) elif enable: transaction.add_post(lambda p: (p in self._fw.policy.get_active_policies_not_derived_from_zone()) and \ self._fw.policy.apply_policy_settings(p), policy) # IPSETS def _ipset_family(self, name): if self._ipset_type(name) == "hash:mac": return None return self._fw.ipset.get_family(name, applied=False) def _ipset_type(self, name): return self._fw.ipset.get_type(name, applied=False) def _ipset_match_flags(self, name, flag): return ",".join([flag] * self._fw.ipset.get_dimension(name)) def _check_ipset_applied(self, name): return self._fw.ipset.check_applied(name) def _check_ipset_type_for_source(self, name): _type = self._ipset_type(name) if _type not in SOURCE_IPSET_TYPES: raise FirewallError( errors.INVALID_IPSET, "ipset '%s' with type '%s' not usable as source" % \ (name, _type)) def _source(self, enable, zone, ipv, source, transaction): # For mac source bindings ipv is an empty string, the mac source will # be added for ipv4 and ipv6 for backend in [self._fw.get_backend_by_ipv(ipv)] if ipv else self._fw.enabled_backends(): if not backend.policies_supported: continue for policy in self._zone_policies[zone]: for (table, chain) in self._fw.policy._get_table_chains_for_zone_dispatch(policy): rules = backend.build_zone_source_address_rules(enable, zone, policy, source, table, chain) transaction.add_rules(backend, rules) # intra zone forward policy = self.policy_name_from_zones(zone, "ANY") if self.get_settings(zone)["forward"]: rules = backend.build_zone_forward_rules(enable, zone, policy, "filter", source=source) transaction.add_rules(backend, rules) # update policy dispatch for any policy using this zone in ingress # or egress for policy in self._fw.policy.get_policies_not_derived_from_zone(): if zone not in self._fw.policy.list_ingress_zones(policy) and \ zone not in self._fw.policy.list_egress_zones(policy): continue if policy in self._fw.policy.get_active_policies_not_derived_from_zone() and self._fw.policy.get_policy(policy).applied: # first remove the old set of sources using the current zone # settings. if not enable and len(self.list_sources(zone)) == 1: self._fw.policy.unapply_policy_settings(policy, use_transaction=transaction) else: self._fw.policy._ingress_egress_zones(False, policy, transaction) # after the transaction ends and therefore the sources # has been added to the zone's settings, update the # dependent policies transaction.add_post(lambda p: (p in self._fw.policy.get_active_policies_not_derived_from_zone()) and \ self._fw.policy._ingress_egress_zones_transaction(True, p), policy) elif enable: transaction.add_post(lambda p: (p in self._fw.policy.get_active_policies_not_derived_from_zone()) and \ self._fw.policy.apply_policy_settings(p), policy) def add_service(self, zone, service, timeout=0, sender=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.add_service(p_name, service, timeout, sender) return zone def remove_service(self, zone, service): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.remove_service(p_name, service) return zone def query_service(self, zone, service): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") return self._fw.policy.query_service(p_name, service) def list_services(self, zone): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") return self._fw.policy.list_services(p_name) def add_port(self, zone, port, protocol, timeout=0, sender=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.add_port(p_name, port, protocol, timeout, sender) return zone def remove_port(self, zone, port, protocol): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.remove_port(p_name, port, protocol) return zone def query_port(self, zone, port, protocol): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") return self._fw.policy.query_port(p_name, port, protocol) def list_ports(self, zone): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") return self._fw.policy.list_ports(p_name) def add_source_port(self, zone, source_port, protocol, timeout=0, sender=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.add_source_port(p_name, source_port, protocol, timeout, sender) return zone def remove_source_port(self, zone, source_port, protocol): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.remove_source_port(p_name, source_port, protocol) return zone def query_source_port(self, zone, source_port, protocol): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") return self._fw.policy.query_source_port(p_name, source_port, protocol) def list_source_ports(self, zone): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") return self._fw.policy.list_source_ports(p_name) def _rich_rule_to_policies(self, zone, rule): zone = self._fw.check_zone(zone) if type(rule.action) == Rich_Mark: return [self.policy_name_from_zones(zone, "ANY")] elif type(rule.element) in [Rich_Service, Rich_Port, Rich_Protocol, Rich_SourcePort]: return [self.policy_name_from_zones(zone, "HOST")] elif type(rule.element) in [Rich_IcmpBlock, Rich_IcmpType]: return [self.policy_name_from_zones(zone, "HOST"), self.policy_name_from_zones(zone, "ANY")] elif type(rule.element) in [Rich_ForwardPort]: return [self.policy_name_from_zones(zone, "ANY")] elif type(rule.element) in [Rich_Masquerade]: return [self.policy_name_from_zones("ANY", zone)] elif rule.element is None: return [self.policy_name_from_zones(zone, "HOST")] else: raise FirewallError("Rich rule type (%s) not handled." % (type(rule.element))) def add_rule(self, zone, rule, timeout=0, sender=None): for p_name in self._rich_rule_to_policies(zone, rule): self._fw.policy.add_rule(p_name, rule, timeout, sender) return zone def remove_rule(self, zone, rule): for p_name in self._rich_rule_to_policies(zone, rule): self._fw.policy.remove_rule(p_name, rule) return zone def query_rule(self, zone, rule): ret = True for p_name in self._rich_rule_to_policies(zone, rule): ret = ret and self._fw.policy.query_rule(p_name, rule) return ret def list_rules(self, zone): zone = self._fw.check_zone(zone) ret = set() for p_name in [self.policy_name_from_zones(zone, "ANY"), self.policy_name_from_zones(zone, "HOST"), self.policy_name_from_zones("ANY", zone)]: ret.update(set(self._fw.policy.list_rules(p_name))) return list(ret) def add_protocol(self, zone, protocol, timeout=0, sender=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.add_protocol(p_name, protocol, timeout, sender) return zone def remove_protocol(self, zone, protocol): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.remove_protocol(p_name, protocol) return zone def query_protocol(self, zone, protocol): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") return self._fw.policy.query_protocol(p_name, protocol) def list_protocols(self, zone): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") return self._fw.policy.list_protocols(p_name) def add_masquerade(self, zone, timeout=0, sender=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones("ANY", zone) self._fw.policy.add_masquerade(p_name, timeout, sender) return zone def remove_masquerade(self, zone): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones("ANY", zone) self._fw.policy.remove_masquerade(p_name) return zone def query_masquerade(self, zone): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones("ANY", zone) return self._fw.policy.query_masquerade(p_name) def add_forward_port(self, zone, port, protocol, toport=None, toaddr=None, timeout=0, sender=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "ANY") self._fw.policy.add_forward_port(p_name, port, protocol, toport, toaddr, timeout, sender) return zone def remove_forward_port(self, zone, port, protocol, toport=None, toaddr=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "ANY") self._fw.policy.remove_forward_port(p_name, port, protocol, toport, toaddr) return zone def query_forward_port(self, zone, port, protocol, toport=None, toaddr=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "ANY") return self._fw.policy.query_forward_port(p_name, port, protocol, toport, toaddr) def list_forward_ports(self, zone): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "ANY") return self._fw.policy.list_forward_ports(p_name) def add_icmp_block(self, zone, icmp, timeout=0, sender=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.add_icmp_block(p_name, icmp, timeout, sender) p_name = self.policy_name_from_zones(zone, "ANY") self._fw.policy.add_icmp_block(p_name, icmp, timeout, sender) return zone def remove_icmp_block(self, zone, icmp): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.remove_icmp_block(p_name, icmp) p_name = self.policy_name_from_zones(zone, "ANY") self._fw.policy.remove_icmp_block(p_name, icmp) return zone def query_icmp_block(self, zone, icmp): zone = self._fw.check_zone(zone) p_name_host = self.policy_name_from_zones(zone, "HOST") p_name_fwd = self.policy_name_from_zones(zone, "ANY") return self._fw.policy.query_icmp_block(p_name_host, icmp) and \ self._fw.policy.query_icmp_block(p_name_fwd, icmp) def list_icmp_blocks(self, zone): zone = self._fw.check_zone(zone) p_name_host = self.policy_name_from_zones(zone, "HOST") p_name_fwd = self.policy_name_from_zones(zone, "ANY") return sorted(set(self._fw.policy.list_icmp_blocks(p_name_host) + self._fw.policy.list_icmp_blocks(p_name_fwd))) def add_icmp_block_inversion(self, zone, sender=None): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.add_icmp_block_inversion(p_name, sender) p_name = self.policy_name_from_zones(zone, "ANY") self._fw.policy.add_icmp_block_inversion(p_name, sender) return zone def _icmp_block_inversion(self, enable, zone, transaction): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy._icmp_block_inversion(enable, p_name, transaction) p_name = self.policy_name_from_zones(zone, "ANY") self._fw.policy._icmp_block_inversion(enable, p_name, transaction) def remove_icmp_block_inversion(self, zone): zone = self._fw.check_zone(zone) p_name = self.policy_name_from_zones(zone, "HOST") self._fw.policy.remove_icmp_block_inversion(p_name) p_name = self.policy_name_from_zones(zone, "ANY") self._fw.policy.remove_icmp_block_inversion(p_name) return zone def query_icmp_block_inversion(self, zone): zone = self._fw.check_zone(zone) p_name_host = self.policy_name_from_zones(zone, "HOST") p_name_fwd = self.policy_name_from_zones(zone, "ANY") return self._fw.policy.query_icmp_block_inversion(p_name_host) and \ self._fw.policy.query_icmp_block_inversion(p_name_fwd) def _forward(self, enable, zone, transaction): p_name = self.policy_name_from_zones(zone, "ANY") for interface in self._zones[zone].settings["interfaces"]: for backend in self._fw.enabled_backends(): if not backend.policies_supported: continue rules = backend.build_zone_forward_rules(enable, zone, p_name, "filter", interface=interface) transaction.add_rules(backend, rules) for ipv,source in self._zones[zone].settings["sources"]: for backend in [self._fw.get_backend_by_ipv(ipv)] if ipv else self._fw.enabled_backends(): if not backend.policies_supported: continue rules = backend.build_zone_forward_rules(enable, zone, p_name, "filter", source=source) transaction.add_rules(backend, rules) def __forward_id(self): return True def add_forward(self, zone, timeout=0, sender=None, use_transaction=None): _zone = self._fw.check_zone(zone) self._fw.check_timeout(timeout) self._fw.check_panic() _obj = self._zones[_zone] forward_id = self.__forward_id() if forward_id in _obj.settings["forward"]: raise FirewallError(errors.ALREADY_ENABLED, "forward already enabled in '%s'" % _zone) if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction if _obj.applied: self._forward(True, _zone, transaction) self.__register_forward(_obj, forward_id, timeout, sender) transaction.add_fail(self.__unregister_forward, _obj, forward_id) if use_transaction is None: transaction.execute(True) return _zone def __register_forward(self, _obj, forward_id, timeout, sender): _obj.settings["forward"][forward_id] = \ self.__gen_settings(timeout, sender) def remove_forward(self, zone, use_transaction=None): _zone = self._fw.check_zone(zone) self._fw.check_panic() _obj = self._zones[_zone] forward_id = self.__forward_id() if forward_id not in _obj.settings["forward"]: raise FirewallError(errors.NOT_ENABLED, "forward not enabled in '%s'" % _zone) if use_transaction is None: transaction = self.new_transaction() else: transaction = use_transaction if _obj.applied: self._forward(False, _zone, transaction) transaction.add_post(self.__unregister_forward, _obj, forward_id) if use_transaction is None: transaction.execute(True) return _zone def __unregister_forward(self, _obj, forward_id): if forward_id in _obj.settings["forward"]: del _obj.settings["forward"][forward_id] def query_forward(self, zone): return self.__forward_id() in self.get_settings(zone)["forward"]