a i+J@sgdZddlZddlZddlZddlZddlZddlZddlZddlm Z ddl m Z m Z dde ddDZdd Zd d ZdUd dZddZddZddZddZddZddZddZddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)d*Zd+d,Z d-d.Z!d/d0Z"d1d2Z#d3d4Z$d5d6Z%d7d8Z&d9d:Z'd;d<Z(d=d>Z)d?d@Z*dAdBZ+dCdDZ,dEdFZ-dGdHZ.dIdJZ/dKdLZ0dMdNZ1dOdPZ2dQdRZ3dSdTZ4dS)V)! getPortID getPortRangeportStrgetServiceNamecheckIPcheckIP6 checkIPnMask checkIP6nMask checkProtocolcheckInterface checkUINT16 checkUINT32firewalld_is_activetempFilereadfile writefileenable_ip_forwarding check_port check_addresscheck_single_address check_macuniqify ppid_of_pidmax_zone_name_len checkUsercheckUid checkCommand checkContextjoinArgs splitArgsmax_policy_name_lencheckTcpMssClampstripNonPrintableCharactersN)log)FIREWALLD_TEMPDIRFIREWALLD_PIDFILEcCs"i|]}|dkr|dks|dqS)N).0ir(r(6/usr/lib/python3.9/site-packages/firewall/functions.py +sr,c Cstt|tr|}nT|r|}z t|}Wn:tybzt|}Wntjy\YYdS0Yn0|dkrpdS|S)z Check and Get port id from port string or port id using socket.getservbyname @param port port string or port id @return Port id if valid, -1 if port can not be found and -2 if port is too big ) isinstanceintstrip ValueErrorsocketZ getservbynameerror)portZ_idr(r(r+r4s   rcCst|tst|tr|St|ts*|rDt|}|dkr@|fS|S|d}t|dkr|dr|drt|d}t|d}|dkr|dkr||kr||fS||kr||fS|fSg}tt|ddD]}td |d|}d ||d}t|dkrlt|}|dkr|dkr||krD| ||fn&||kr^| ||fn | |fq|dkr| |f|t|krqqt|dkrdSt|dkrdS|dS)aI Get port range for port range string or single port id @param ports an integer or port string or port range string @return Array containing start and end port id for a valid range or -1 if port can not be found and -2 if port is too big for integer input or -1 for invalid ranges or None if the range is ambiguous. r"-r.N) r1tuplelistr2isdigitrsplitlenrangejoinappend)ZportsZid1splitsZid2Zmatchedr*Zport2r(r(r+rKsL $      r:cCsX|dkr dSt|}t|tr*|dkr*dSt|dkr>d|Sd|d||dfSdS)a Create port and port range string @param port port or port range int or [int, int] @param delimiter of the output string for port ranges, default ':' @return Port or port range string, empty string if port isn't specified, None if port or port range is not valid r"Nr:z%sz%s%s%s)rr1r2r?)r7Z delimiter_ranger(r(r+rs rcCst|}t|}t|dkrt|dkr@t|dt|dkSt|dkrt|dt|dkrt|dt|dkrdSn|t|dkrt|dkrt|dt|dkrt|dt|dkrt|dt|dkrt|dt|dkrdSdS)Nr:r"r9TF)rr?r)r7r@Z_portrFr(r(r+portInPortRanges.     rGcCsPt|}t|dkr$|d|df}tt|}ttdd|ddd}g}|D]}|d|dkr|d|dkr||qP|d|dkr|d|dkr|d|dkr|||d|df}qP|d|dkrP|d|dkrP|d|dkrP|||d|df}qPttdd|}|d|dkrF|df}|g|fS)z Coalesce a port range with existing list of port ranges @param new_range tuple/list/string @param ranges list of tuple/list/string @return tuple of (list of ranges added after coalescing, list of removed original ranges) r:r"cSs t|dkr|d|dfS|SNr:r"r?xr(r(r+z#coalescePortRange..cSs|dSNr"r(rJr(r(r+rLrMkeycSs|d|dkr|dfS|SNr"r:r(rJr(r(r+rLrMrr?mapsortedrBr<)Z new_rangerangesZcoalesced_range_rangesremoved_rangesr@r(r(r+coalescePortRanges.         rXcCst|}t|dkr$|d|df}tt|}ttdd|ddd}g}g}|D]@}|d|dkr|d|dkr||qT|d|dkr|d|dkr|d|dkr||||dd|dfqT|d|dkr8|d|dkr8|d|dkr8||||d|ddfqT|d|dkrT|d|dkrT||||d|ddf||dd|dfqTttdd|}ttdd|}||fS) z break a port range from existing list of port ranges @param remove_range tuple/list/string @param ranges list of tuple/list/string @return tuple of (list of ranges added after breaking up, list of removed original ranges) r:r"cSs t|dkr|d|dfS|SrHrIrJr(r(r+rLrMz breakPortRange..cSs|dSrNr(rJr(r(r+rLrMrOcSs|d|dkr|dfS|SrQr(rJr(r(r+rLrMcSs|d|dkr|dfS|SrQr(rJr(r(r+rLrMrR)Z remove_rangerUrVrWZ added_rangesr@r(r(r+breakPortRanges6       $   rYcCs0ztt||}Wntjy*YdS0|S)z Check and Get service name from port and proto string combination using socket.getservbyport @param port string or id @param protocol string @return Service name if port and protocol are valid, else None N)r5Z getservbyportr2r6)r7protonamer(r(r+rs rcCs.zttj|Wntjy(YdS0dS)zh Check IPv4 address. @param ip address string @return True if address is valid, else False FT)r5 inet_ptonZAF_INETr6ipr(r(r+rs rcCs |dS)z Normalize the IPv6 address This is mostly about converting URL-like IPv6 address to normal ones. e.g. [1234::4321] --> 1234:4321 z[])r3r]r(r(r+ normalizeIP6sr_cCs2zttjt|Wntjy,YdS0dS)zh Check IPv6 address. @param ip address string @return True if address is valid, else False FT)r5r\ZAF_INET6r_r6r]r(r(r+rs rcCs|d}|dkr<|d|}||dd}|r6|sDdSn|}d}t|sPdS|rd|vrdt|Sz t|}WntyYdS0|dks|dkrdSdS) N/r.r:F.r" T)findrr2r4r^indexaddrmaskr*r(r(r+r*s(    rcCs |tSN) translateNOPRINT_TRANS_TABLE)Zrule_strr(r(r+r!Bsr!cCs|d}|dkr<|d|}||dd}|r6|sDdSn|}d}t|sPdS|rz t|}WntytYdS0|dks|dkrdSdS)Nr`r.r:Fr"T)rcrr2r4rdr(r(r+rEs$    rc Cs`z t|}Wn:tyFzt|Wntjy@YYdS0Yn0|dksX|dkr\dSdS)NFr"T)r2r4r5Zgetprotobynamer6)Zprotocolr*r(r(r+r [s  r cCs:|r6|rt|dkr6dSn|dkr*dS|dkr6dSdS)NiFNoneTZpmtu)r=r2)Ztcp_mss_clamp_valuer(r(r+r js r cCs0|rt|dkrdSdD]}||vrdSqdS)z Check interface string @param interface string @return True if interface is valid (maximum 16 chars and does not contain ' ', '/', '!', ':', '*'), else False F) r`!*TrI)Zifacechr(r(r+r us r cCs<zt|d}Wnty"YdS0|dkr8|dkr8dSdS)Nr"Fr/Tr2r4valrKr(r(r+r s r cCs<zt|d}Wnty"YdS0|dkr8|dkr8dSdS)Nr"FlTrsrtr(r(r+r s r cCstjtsdSz6ttd}|}Wdn1s:0YWntyZYdS0tjd|spdSz:td|d}|}Wdn1s0YWntyYdS0d|vrdSdS)zv Check if firewalld is active @return True if there is a firewalld pid file and the pid is used by firewalld FrNz/proc/%sz/proc/%s/cmdlineZ firewalldT)ospathexistsr%openreadline Exception)fdpidZcmdliner(r(r+r s"  * * r c Csfz,tjtsttdtjddtddWSty`}zt d|WYd}~n d}~00dS)NiZwtztemp.F)modeprefixdirdeletez#Failed to create temporary file: %s) rwrxryr$mkdirtempfileZNamedTemporaryFiler|r#r6)msgr(r(r+rs  rc Cstz8t|d}|WdWS1s,0YWn6tyn}ztd||fWYd}~n d}~00dS)NrvzFailed to read file "%s": %s)rz readlinesr|r#r6)filenamefer(r(r+rs  ,(rc Csvz8t|d}||Wdn1s,0YWn8typ}z td||fWYd}~dSd}~00dS)Nwz Failed to write to file "%s": %sFT)rzwriter|r#r6)rlinerrr(r(r+rs ,rcCs(|dkrtddS|dkr$tddSdS)Nipv4z/proc/sys/net/ipv4/ip_forwardz1 ipv6z&/proc/sys/net/ipv6/conf/all/forwardingF)r)ipvr(r(r+rs   rcCs|ddddS)N_r8z nf-conntrack-rE)replace)moduler(r(r+get_nf_conntrack_short_namesrcCst|}|dks<|dks<|dus 65535z'%s': port is invalidz'%s': port is ambiguousz'%s': range start >= endFT)rr?r#Zdebug2)r7rFr(r(r+rs  rcCs(|dkrt|S|dkr t|SdSdSNrrF)rrrsourcer(r(r+rs rcCs(|dkrt|S|dkr t|SdSdSr)rrrr(r(r+rs rcCsNt|dkrJdD]}||dkrdSqdD]}||tjvr,dSq,dSdS)N)r9 rDF) r"r: rnT)r?stringZ hexdigits)Zmacr*r(r(r+rs  rcCs$g}|D]}||vr||q|Srh)rB)Z_listoutputrKr(r(r+r s  rcCsHz.td|}t|d}|WntyBYdS0|S)z Get parent for pid zps -o ppid -h -p %d 2>/dev/nullr"N)rwpopenr2rr3closer|)r~rr(r(r+rs  rcCsBddlm}ddlm}ttt|}d|t|tdS)z iptables limits length of chain to (currently) 28 chars. The longest chain we create is POST__allow, which leaves 28 - 11 = 17 chars for . r")POLICY_CHAIN_PREFIX SHORTCUTSZ_allow)Zfirewall.core.ipXtablesrfirewall.core.basermaxrSr?values)rrlongest_shortcutr(r(r+rs  rcCs.ddlm}ttt|}d|tdS)z Netfilter limits length of chain to (currently) 28 chars. The longest chain we create is POST__allow, which leaves 28 - 11 = 17 chars for . r"rrZ__allow)rrrrSr?r)rrr(r(r+r's rcCsRt|dkst|tdkr"dS|D]&}|tjvr&|tjvr&|dvr&dSq&dS)Nr:SC_LOGIN_NAME_MAXF)rar8r$T)r?rwsysconfr ascii_lettersdigits)usercr(r(r+r1s rcCsDt|tr,z t|}Wnty*YdS0|dkr@|dkr@dSdS)NFr"iT)r1strr2r4)uidr(r(r+r;s   rcCsHt|dkst|dkrdSdD]}||vr dSq |ddkrDdSdS)Nr:iF)| r"r`TrI)Zcommandrrr(r(r+rEs rcCs|d}t|dvrdS|ddkr>|ddddkr>dS|dddd krVdS|d ddd krndSt|d dkrdSd S)NrD)rrFr"rootr0Z_ur:Z_rr9Z_trT)r>r?)contextrCr(r(r+rOs   rcCs8dttvr ddd|DSddd|DSdS)Nquoterocss|]}t|VqdSrh)shlexrr)ar(r(r+ crMzjoinArgs..css|]}t|VqdSrh)pipesrrr(r(r+rerM)rrrA)argsr(r(r+ras rcCs t|Srh)rr>)Z_stringr(r(r+rgsr)rD)5__all__r5rwZos.pathrrrrZfirewall.core.loggerr#Zfirewall.configr$r%r@rjrrrrGrXrYrrr_rrr!rr r r r r r rrrrrrrrrrrrrrrrrrrr(r(r(r+sd   : &+