3 @)f'K#@sdddddddddd d d d d ddddddddddddddddddd d!d"g#Zd#d$lZd#d$lZd#d$lZd#d$lZd#d$lZd#d$lZd#d$lZd#d$lZd#d%l m Z d#d&l m Z m Z ejd'kZd(d)ed#d*DZd+dZd,dZdXd.dZd/d0Zd1d2Zd3d4Zd5dZd6dZd7d8Zd9dZd:dZd;d"Zdd Z d?d Z!d@d Z"dAd Z#dBdZ$dCdZ%dDdZ&dEdFZ'dGdZ(dHdZ)dIdZ*dJdZ+dKdZ,dLdZ-dMd!Z.dNdZ/dOdZ0dPdZ1dQdZ2dRdZ3dSdZ4dTdZ5dUdZ6dVdZ7dWd Z8d$S)YPY2 getPortID getPortRangeportStrgetServiceNamecheckIPcheckIP6 checkIPnMask checkIP6nMask checkProtocolcheckInterface checkUINT32firewalld_is_activetempFilereadfile writefileenable_ip_forwarding check_port check_addresscheck_single_address check_macuniqify ppid_of_pidmax_zone_name_len checkUsercheckUid checkCommand checkContextjoinArgs splitArgsb2uu2b u2b_if_py2max_policy_name_lenstripNonPrintableCharactersN)log)FIREWALLD_TEMPDIRFIREWALLD_PIDFILE3cCs"i|]}|dko|dksd|qS)N).0ir+r+/usr/lib/python3.6/functions.py .sr/cCstt|tr|}nT|r|j}y t|}Wn:tk rbytj|}Wntjk r\dSXYnX|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 i) isinstanceintstrip ValueErrorsocketZ getservbynameerror)portZ_idr+r+r.r7s   cCst|tst|tr|St|ts*|jrDt|}|dkr@|fS|S|jd}t|dkr|djr|djrt|d}t|d}|dkr|dkr||kr||fS||kr||fS|fSg}xtt|ddD]}tdj |d|}dj ||d}t|dkrnt|}|dkr|dkr||krF|j ||fn&||kr`|j ||fn |j |fq|dkr|j |f|t|krPqWt|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$-r2r1Nr3r3) r5tuplelistr6isdigitrsplitlenrangejoinappend)ZportsZid1splitsZid2Zmatchedr-Zport2r+r+r.rNsL $      :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$Nr1z%sz%s%s%s)rr5r6rA)r;Z delimiter_ranger+r+r.rs cCst|}t|}t|dkrt|dkr@t|dt|dkSt|dkrt|dt|dkrt|dt|dkrdSn|t|dkrt|dkrt|dt|dkrt|dt|dkrt|dt|dkrt|dt|dkrdSdS)Nr1r$r2TF)rrAr)r;rBZ_portrHr+r+r.portInPortRanges   0  00rIcCsTt|}t|dkr$|d|df}tt|}ttdd|ddd}g}x|D]}|d|dkr|d|dkr|j|qR|d|dkr|d|dkr|d|dkr|j||d|df}qR|d|dko|d|dko|d|dkrR|j||d|df}qRWttdd|}|d|dkrJ|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) r1r$cSs t|dkr|d|dfS|S)Nr1r$)rA)xr+r+r.sz#coalescePortRange..cSs|dS)Nr$r+)rJr+r+r.rKs)keycSs|d|dkr|dfS|S)Nr$r1r+)rJr+r+r.rKs)rrAmapsortedrDr>)Z new_rangerangesZcoalesced_range_rangesremoved_rangesrBr+r+r.coalescePortRanges*          rRcCst|}t|dkr$|d|df}tt|}ttdd|ddd}g}g}xJ|D]@}|d|dkr|d|dkr|j|qX|d|dkr|d|dkr|d|dkr|j||j|dd|dfqX|d|dkr<|d|dkr<|d|dkr<|j||j|d|ddfqX|d|dkrX|d|dkrX|j||j|d|ddf|j|dd|dfqXWttdd|}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) r1r$cSs t|dkr|d|dfS|S)Nr1r$)rA)rJr+r+r.rKsz breakPortRange..cSs|dS)Nr$r+)rJr+r+r.rKs)rLcSs|d|dkr|dfS|S)Nr$r1r+)rJr+r+r.rKscSs|d|dkr|dfS|S)Nr$r1r+)rJr+r+r.rKs)rrArMrNrDr>)Z remove_rangerOrPrQZ added_rangesrBr+r+r.breakPortRanges2      $   rSc Cs0ytjt||}Wntjk r*dSX|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)r9Z getservbyportr6r:)r;protonamer+r+r.rs c Cs.ytjtj|Wntjk r(dSXdS)zl Check IPv4 address. @param ip address string @return True if address is valid, else False FT)r9 inet_ptonZAF_INETr:)ipr+r+r.r s cCs |jdS)z Normalize the IPv6 address This is mostly about converting URL-like IPv6 address to normal ones. e.g. [1234::4321] --> 1234:4321 z[])r7)rWr+r+r. normalizeIP6srXc Cs2ytjtjt|Wntjk r,dSXdS)zl Check IPv6 address. @param ip address string @return True if address is valid, else False FT)r9rVZAF_INET6rXr:)rWr+r+r.r s c Csd|krN|d|jd}||jddd}t|dksHt|dkrVdSn|}d}t|sbdS|rd|krvt|Sy t|}Wntk rdSX|dks|dkrdSdS)N/r1F.r$ T)indexrArr6r8)rWaddrmaskr-r+r+r.r-s& cCs |jtS)N) translateNOPRINT_TRANS_TABLE)Zrule_strr+r+r.r#Dsc Csd|krN|d|jd}||jddd}t|dksHt|dkrVdSn|}d}t|sbdS|ry t|}Wntk rdSX|dks|dkrdSdS)NrYr1Fr$T)r\rArr6r8)rWr]r^r-r+r+r.r Gs" cCs`y t|}Wn:tk rFytj|Wntjk r@dSXYnX|dksX|dkr\dSdS)NFr$T)r6r8r9Zgetprotobynamer:)Zprotocolr-r+r+r.r \s  cCs4| st|dkrdSxdD]}||krdSqWdS) z Check interface string @param interface string @return True if interface is valid (maximum 16 chars and does not contain ' ', '/', '!', ':', '*'), else False F rY!*T)rdrYrerf)rA)Zifacechr+r+r.r ks  c Cs<yt|d}Wntk r"dSX|dkr8|dkr8dSdS)Nr$FlT)r6r8)valrJr+r+r.r ~scCstjjtsdSy"ttd}|j}WdQRXWntk rFdSXtjjd|s\dSy&td|d}|j}WdQRXWntk rdSXd|krdSdS)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"  cCsby*tjjtstjtdtjddtddStk r\}ztj d|WYdd}~XnXdS)NiZwtztemp.F)modeprefixdirdeletez#Failed to create temporary file: %s) rjrkrlr&mkdirtempfileZNamedTemporaryFileror%r:)msgr+r+r.rs   cCsXyt|d }|jSQRXWn4tk rR}ztjd||fWYdd}~XnXdS)NrizFailed to read file "%s": %s)rm readlinesror%r:)filenamefer+r+r.rs  $cCs\y$t|d}|j|WdQRXWn2tk rV}ztjd||fdSd}~XnXdS)Nwz Failed to write to file "%s": %sFT)rmwriteror%r:)rzliner{r|r+r+r.rs cCs(|dkrtddS|dkr$tddSdS)Nipv4z/proc/sys/net/ipv4/ip_forwardz1 ipv6z&/proc/sys/net/ipv6/conf/all/forwardingF)r)ipvr+r+r.rs   cCs|jddjddS)N_r<z nf-conntrack-rG)replace)moduler+r+r.get_nf_conntrack_short_namesrcCst|}|d ks<|d ks<|dks 65535z'%s': port is invalidz'%s': port is ambiguousz'%s': range start >= endFTr4r3r4r3)rrAr%Zdebug2)r;rHr+r+r.rscCs(|dkrt|S|dkr t|SdSdS)NrrF)rr )rsourcer+r+r.rs cCs(|dkrt|S|dkr t|SdSdS)NrrF)rr)rrr+r+r.rs c CsRt|dkrNxdD]}||dkrdSqWxdD]}||tjkr0dSq0WdSdS)N r2 rFFr$r1 rcT)r2rrrr) r$r1rrrrrrrrrrc)rAstringZ hexdigits)Zmacr-r+r+r.rs    cCs(g}x|D]}||kr |j|q W|S)N)rD)Z_listoutputrJr+r+r.rs  c CsHy.tjd|}t|jdj}|jWntk rBdSX|S)z Get parent for pid zps -o ppid -h -p %d 2>/dev/nullr$N)rjpopenr6ryr7closero)rqr{r+r+r.rs cCsBddlm}ddlm}ttt|j}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.basermaxrMrAvalues)rrlongest_shortcutr+r+r.r" s  cCs.ddlm}ttt|j}d|tdS)z Netfilter limits length of chain to (currently) 28 chars. The longest chain we create is FWDI__allow, which leaves 28 - 11 = 17 chars for . r$)rrZ__allow)rrrrMrAr)rrr+r+r.rs cCsTt|dkst|tjdkr"dSx,|D]$}|tjkr(|tjkr(|d kr(dSq(WdS) Nr1SC_LOGIN_NAME_MAXFrZr<r$T)rZr<rr)rArjsysconfrZ ascii_lettersZdigits)usercr+r+r.rs   c CsDt|tr,y t|}Wntk r*dSX|dkr@|dkr@dSdS) NFr$r2r)r1Tli)r5strr6r8)Zuidr+r+r.r(s  cCsJt|dkst|dkrdSxd D]}||kr"dSq"W|ddkrFdSd S) Nr1iF| r$rYT)rrr)rA)Zcommandrgr+r+r.r2s  cCs|jd}t|dkrdS|ddkr>|ddddkr>dS|d ddd krVdS|dddd krndSt|d d krdSd S)NrFrrFr$rootr2Z_ur1Z_rZ_trT)rrr4r4r4)r@rA)contextrEr+r+r.r<s   cCs8dttkr djdd|DSdjdd|DSdS)Nquoterdcss|]}tj|VqdS)N)shlexr)r,ar+r+r. PszjoinArgs..css|]}tj|VqdS)N)pipesr)r,rr+r+r.rRs)rtrrC)argsr+r+r.rNs cCs8tr*t|tr*t|}tj|}tt|Stj|SdS)N)rr5unicoder rr@rMr)_stringrEr+r+r.rTs   cCst|tr|jddS|S)z bytes to unicode zUTF-8r)r5bytesdecode)rr+r+r.r]s  cCst|ts|jddS|S)z unicode to bytes zUTF-8r)r5rencode)rr+r+r.r cs  cCstrt|tr|jddS|S)z" unicode to bytes only if Python 2zUTF-8r)rr5rr)rr+r+r.r!is )rF)9__all__r9rjZos.pathrrrsysrwZfirewall.core.loggerr%Zfirewall.configr&r'versionrrBr`rrrrIrRrSrrrXrrr#r r r r r rrrrrrrrrrrr"rrrrrrrrr r!r+r+r+r.sz   : &+