
    e                     2   d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlZddlZddlZddlZddlmZ ddlmZmZ dZdZg dZg dZd	d
gZd Zd Zd Zd Zd Zd9dZd Z d Z!d Z"d Z#d:dZ$d Z%d Z&d Z'd:dZ(d Z)ejT                  dfdZ+d Z,d Z-d Z.d  Z/ e	j`                         fd!Z1 e	j`                         fd"Z2d# Z3d$ Z4d% Z5d& Z6d' Z7d( Z8d) Z9d* Z:d;d+Z;d<d,Z<d- Z=d=d.Z>d/ Z?d0 Z@d1 ZAd2 ZBd3 ZCd4 ZDd5 ZEd6 ZFd>d7ZGd8 ZHy)?z"util.py: utility functions for ufw    )print_functionN)reduce)mkstempmktempF)tcpudpipv6espahigmpgrevrrp)r	   r
   r   r   r   r   r	   r   c                    d}	 t        j                  |        	 t        j                  | d       d}	 t        j                  | d       |dk(  rd}|S d}	 |S # t        $ r  w xY w# t        $ r Y >w xY w# t        $ r Y |S w xY w)z8Get the protocol for a specified port from /etc/services r   r   any)socketgetservbyname	Exception)portprotos     */usr/lib/python3/dist-packages/ufw/util.pyget_services_protor   .   s    ET"T5)T5)E>E L	 E L%      Ls3   A A% A4 A4 A"%	A10A14	B Bc                    d}d}| j                  d      }t        |      dk(  r|d   }d}||fS t        |      dk(  r/|d   }|d   }|t        v rt        d|z        }t	        |      ||fS t        d      }t	        |      )	zParse port or port and protocolr   /   r   r      zInvalid port with protocol '%s'zBad port)splitlenportless_protocols_
ValueError)p_strr   r   tmperr_msgs        r   parse_port_protor%   H   s    DE
++c
C
3x1}1v %= 
SQ1vA&&9EABGW%% %= J-!!    c                 p   t         j                  st        d       yt        |       dkD  st	        j
                  d|       sy| j                  d      }	 t        j                  t         j                  |d          t        |      dkD  ryt        |      dk(  rt        |d   d	      syy	# t        $ r Y yw xY w)
zVerifies if valid IPv6 addressz"python does not have IPv6 support.F+   z^[a-fA-F0-9:\./]+$r   r   r   r   T)r   has_ipv6warnr   rematchr   	inet_ptonAF_INET6r   _valid_cidr_netmaskaddrnets     r   valid_address6r3   \   s    ??12 4y2~RXX&;TB
**S/C#a&1 3x!|	SQ"3q640  s   'B) )	B54B5c                 Z   t        |       dkD  st        j                  d|       sy| j                  d      }	 t	        j
                  t        j                  |d          t        |d   d      sy	 t        |      dkD  ryt        |      dk(  rt        |d   d      syy# t        $ r Y yw xY w)	zVerifies if valid IPv4 address   z^[0-9\./]+$Fr   r   r   r   T)
r   r+   r,   r   r   r-   AF_INET_valid_dotted_quadsr   valid_netmaskr0   s     r   valid_address4r9   v   s     4y2~RXXnd;
**S/CQ0"3q651 2
 3x!|	SQSVU+  s   6B 	B*)B*c                 6    t        | |      xs t        | |      S )z(Verifies if valid cidr or dotted netmask)r/   r7   )nmv6s     r   r8   r8      s    r2&E*=b"*EEr&   c                     |dk(  rt        |       S |dk(  rt        |       S |dk(  rt        |       xs t        |       S t        )zValidate IP addresses64r   )r3   r9   r!   )r1   versions     r   valid_addressrA      sI    #~d##	Cd##	E	d#;~d';;
r&   c                    g }d}d}t         j                  }|rd}t         j                  }d| v r5| j                  d      }|r|d   dk(  r|d= n'|s%|d   dk(  s|d   dk(  r|d= n|j	                  |        |s0t        |      d	k(  r"t        |d   |      r	 t        |d   |      |d<   |d
   }t        j                  |t        j                  ||            }||d
   k7  rd}t        |      d	k(  r5|d|d   z   z  }|s(t        |      }||k7  rd|d|d}t        |       |}d}t        ||      sd|z  }t        |       t        ||fS # t        $ r Y w xY w)zConvert address to standard form. Use no netmask for IP addresses. If
       netmask is specified and not all 1's, for IPv4 use cidr if possible,
       otherwise dotted netmask and for IPv6, use cidr.
    Fr?   r>   r   r   12832z255.255.255.255r   r   TzUsing 'z' for address ''zInvalid address '%s')r   r6   r.   r   appendr   r7   _dotted_netmask_to_cidrr   	inet_ntopr-   _address4_to_networkdebugrA   r!   )	origr<   r2   changedr@   s_typer1   networkdbg_msgs	            r   normalize_addressrP      s|   
 CGG^^F	
d{jjo#a&E/AQ43q65F+FA

4#c(a-$7A$C	,SVR8CF
 q6D FF$4$4VT$BCDs1v~
3x1}c!f*40G$;BDIgw'(D1g'?5  		s   E	 		EEc                     t        | d      S )z"Opens the specified file read-onlyr)open)fns    r   open_file_readrU      s    C=r&   c                 ~    t        |       }	 t               \  }}|| ||dS # t        $ r |j                           w xY w)z=Opens the specified file read-only and a tempfile read-write.)rK   orignamer#   tmpname)rU   r   r   close)rT   rK   r#   rX   s       r   
open_filesrZ      sJ    "D g
 r#'KK	  

s   ! <c                    |dk(  ry| st        t        j                  d      t        r7| t        j
                  j                         k(  rt        j                  |       yd}t        j                  d   dk\  r!t        j                  | t        |d            }nt        j                  | |      }|dk  rt        t        j                  d      y)	z~Write to the file descriptor and error out of 0 bytes written. Intended
       to be used with open_files() and close_files().r   NzNot a valid file descriptorr      asciiz"Could not write to file descriptor)OSErrorerrnoENOENT
msg_outputsysstdoutfilenowriteversion_infoosbytesEIO)fdoutrcs      r   write_to_filern      s     byell$ABB bCJJ--//	B
aXXb%W-.XXb#	Qweii!EFF r&   Tc                     | d   j                          t        j                   | d          |r8t        j                  | d   | d          t        j                  | d   | d          t        j
                  | d          y)zuCloses the specified files (as returned by open_files), and update
       original file with the temporary file.
    rK   r#   rW   rX   N)rY   rh   shutilcopystatcopyunlink)fnsupdates     r   close_filesrv     sc     KHHSZJY8C	NC
O4IIc)nr&   c                    t        |        	 t        j                  | t        j                  t        j                  d      }|j                         d   }|j                  t        |      gS # t
        $ r}dt        |      gcY d}~S d}~ww xY w)z!Try to execute the given command.T)rd   stderruniversal_newlines   Nr   )	rJ   
subprocessPopenPIPESTDOUTr_   strcommunicate
returncode)commandspexrl   s       r   cmdr     sx    	'Ngjoo%/%6%6157 ..
1
CMM3s8$$	  SW~s   5A, ,	B5BBBc                 *   	 t        j                  | t         j                        }t        j                  ||j                        }|j                         d   }|j                  t        |      gS # t        $ r}dt        |      gcY d}~S d}~ww xY w)z#Try to pipe command1 into command2.)rd   )stdinrz   Nr   )r{   r|   r}   rd   r_   r   r   r   )command1command2sp1sp2r   rl   s         r   cmd_piper   $  sy    x
@xszz: //
A
CNNCH%%	  SW~s   AA2 2	B;BBBc                 R   	 | j                   }	 |j                  dd      }t        r5t	        j
                  t        j                        r|j                  |       n|j                  t        |             | j                          y# t        $ r | }Y w xY w# t        $ r |}Y w xY w)zQImplement our own print statement that will output utf-8 when
       appropriate.utf-8ignoreN)bufferr   encoderb   inspectisclassioStringIOrf   ri   flush)outputswriterrl   s       r   _printr   2  s    hhw)
 goobkk2QU3Z 
LLN    s"   B B BBB&%B&c                     	 t        t        j                  d| z         |rt        j                  d       yy# t        $ r Y $w xY w)zPrint error message and exitz
ERROR: %s
r   N)r   rc   rx   IOErrorexit)rl   do_exits     r   errorr   G  sC    szz=3./    s   8 	AAc                 ^    	 t        t        j                  d| z         y# t        $ r Y yw xY w)zPrint warning messagez	WARN: %s
N)r   rc   rx   r   rl   s    r   r*   r*   R  s,    szz<#-. s     	,,c                     t         r|t        j                  k(  rt         }	 |rt        |d| z         yt        |d| z         y# t        $ r Y yw xY w)zPrint messagez%s
%sN)rb   rc   rd   r   r   )rl   r   newlines      r   msgr   Z  sK    f

*66C<(64#:& s   A A 	AAc                 l    t         r	 t        t        j                  d| z         yy# t        $ r Y yw xY w)zPrint debug messagez
DEBUG: %s
N)	DEBUGGINGr   rc   rx   r   r   s    r   rJ   rJ   h  s6    	3::}s23   		s   ' 	33c                 >    t        |fd| j                  d            S )z
    A word-wrap function that preserves existing line breaks
    and most spaces in the text. Expects that existing line
    breaks are posix newlines (
).
    c           	          | dt        |       | j                  d      z
  dz
  t        |j                  dd      d         z   |k\     |S )Nz 

r   r   )r   rfindr   )linewordwidths      r   <lambda>zword_wrap.<locals>.<lambda>w  sV    #d)DJJt$44q8djjq1!4569>? A	3 r&    )r   r   )textr   s     r   	word_wrapr   q  s%     5 
 **S/ r&   c                     t        | d      S )zWord wrap to a specific widthK   )r   )r   s    r   	wrap_textr     s    T2r&   c                 6    d | j                  fd       y)a$  Sorts list of strings into numeric order, with text case-insensitive.
       Modifies list in place.

       Eg:
       [ '80', 'a222', 'a32', 'a2', 'b1', '443', 'telnet', '3', 'http', 'ZZZ']

       sorts to:
       ['3', '80', '443', 'a2', 'a32', 'a222', 'b1', 'http', 'telnet', 'ZZZ']
    c                 X    | j                         rt        |       S | j                         S N)isdigitintlower)ts    r   r   zhuman_sort.<locals>.<lambda>  s    qyy{SV 	 r&   c                 b    t        j                  d|       D cg c]
  } |       c}S c c}w )Nz([0-9]+))r+   r   )kcnorms     r   r   zhuman_sort.<locals>.<lambda>  s$    bhhz1.EFT!WF Fs   ,)keyN)sort)lstr   s    @r   
human_sortr     s     :DHHFHGr&   c                    	 t        |       }t        j                  j                  dt        |      d      }t        j                  j                  |      st        d|z        t        |      j                         d   j                  dd      d   j                         d   }t        |      S # t        $ r t        d      w xY w)zdFinds parent process id for pid based on /proc/<pid>/stat. See
       'man 5 proc' for details.
    zpid must be an integer/procstatCouldn't find '%s'r   )r   )r   r   r!   rh   pathjoinr   isfiler   rS   	readlinesrsplitr   )mypidpidnameppids       r   get_ppidr     s    3%j 77<<S62D77>>$*d344 :!!$++C3A6<<>qADt9  31223s   B/ /Cc                 x   	 t        |       }| dk(  s|dk  ryt        j                  j                  dt        |      d      }t        j                  j                  |      st        d      |z  }t        |      	 t        |      j                         d   j                         d   }t        d
|z         |dk(  ryt        |      S # t        $ r t        d      }t        |       Y yt        $ r# t        d      t        |       z  }t        |      w xY w# t        $ r t        d	      |z  }t        |      w xY w)z1Determine if current process is running under sshz%Couldn't find pid (is /proc mounted?)Fz!Couldn't find parent pid for '%s'r   r   r   r   r   z"Could not find executable for '%s'zunder_ssh: exe is '%s'z(sshd)T)r   r   r    r*   r   r   r!   rh   r   r   r   rS   r   r   rJ   	under_ssh)r   r   warn_msgr$   r   exes         r   r   r     s/   "} ax41977<<TF3D77>>$()T2!!"4j""$Q'--/2 

"c
*+ h;  <=X "78CHE!!"   "89TB!!"s   C ;-D D(+D#D9c                 v    d}|rd}t        j                  d|       rt        |       dk  st        |       |kD  ryy)zVerifies cidr netmasks       ^[0-9]+$r   FT)r+   r,   r   )r;   r<   nums      r   r/   r/     s7    
C	88K$B!s2w}r&   c                     |ryt        j                  d|       rH| j                  d      }t        |      dk7  ry|D ]"  }|rt	        |      dk  st	        |      dkD  s" y yy)z.Verifies dotted quad ip addresses and netmasksFz^[0-9]+\.[0-9\.]+$.   r      T)r+   r,   r   r   r   )r;   r<   quadsqs       r   r7   r7     se    	88)2.HHSME5zQ !CFQJ#a&3, !  r&   c           	         d}|rt         t        | |      st         d}	 t        t        j                  dt        j                  |             d         }d}t        d      D ]  }||z	  dz  dk(  rd}|rd} n|dz  } |dk\  r|dk  rt        d|z
        }t        ||      st         |S # t        $ r8 t        t        j                  dt        j                  |             d         }Y w xY w)	z@Convert netmask to cidr. IPv6 dotted netmasks are not supported.r   r   >LFr   r   Tr\   )r!   r7   longstructunpackr   	inet_aton	NameErrorr   ranger   r/   )r;   r<   cidrmbitsbits	found_onens          r   rG   rG     s    D	"2r*
	EdF,<,<R,@A!DED 	r 	A	Q!# 	EQJE	 A:%2+rEz?DtR(K)  	Ev}}T6+;+;B+?@CDD	Es   5B, ,>C-,C-c                 B   d}|rt         t        | |      st         	 t        d      }t	        d      D ]  }|t        |       k  s|dd|z
  z  z  } t        j                  t        j                  d|            }t        ||      st         |S # t        $ r d}Y tw xY w)z<Convert cidr to netmask. IPv6 dotted netmasks not supported.r   r   r   r   r5   r   )r!   r/   r   r   r   r   r   	inet_ntoar   packr7   )r   r<   r;   r   r   s        r   _cidr_to_dotted_netmaskr   $  s    	B	"4,
	7D r 	$A3t9}R!V#	$ fkk$56 r2&I  	D	s   B BBc           	         d| vrt        d       | S | j                  d      }t        |      dk7  st        |d   d      st        |d   }|d   }|}t        |d      rt        |d      }	 t        t        j                  dt        j                  |            d         }t        t        j                  dt        j                  |            d         }||z  }t        j                  t        j                  d|            }|d|S # t        $ rm t        t        j                  dt        j                  |            d         }t        t        j                  dt        j                  |            d         }Y w xY w)z8Convert an IPv4 address and netmask to a network addressr   z8_address4_to_network: skipping address without a netmaskr   r   Fr   r   )rJ   r   r   r7   r!   r/   r   r   r   r   r   r   r   r   r   r   )	r1   r#   hostorig_nmr;   	host_bitsnm_bitsnetwork_bitsrN   s	            r   rI   rI   A  sO   
$HI
**S/C
3x1}/A>q6D!fG	B2u%$R/DtV-=-=d-CDQGH	v}}T6+;+;B+?@CD
 w&Lv{{4>?Gw''  DdF,<,<T,BCAFG	fmmD&*:*:2*>?BCDs   +A*D
 
A3F ?F c                    d }d| vrt        d       | S | j                  d      }t        |      dk7  st        |d   d      st        |d   }|d   }t        j                  dt        j                  t        j                  |            }	 t        d      }t        d	      D ]>  } |||   d
      }t        d
      D ]"  }	|dt        ||	         z  d|	z
  |d
z  z
  z  z  }$ @ 	 t        d      }
t        d      D ]  }|t        |      k  s|
dd|z
  z  z  }
 ||
z  }g }t        d	      D ]0  }|j                  t         ||d      |d
z  |d
z  d
z    d             2 t        j                  t        j                  t        j                   d|d   |d   |d   |d   |d   |d   |d   |d   	            }|d|S # t        $ r d}Y 3w xY w# t        $ r d}
Y w xY w)z8Convert an IPv6 address and netmask to a network addressc           	          dj                  t        |dz
  dd      D cg c]  }t        | |z	  dz         c}      S c c}w )zDecimal to binaryr   r   r\   )r   r   r   )r   countys      r   dec2binz%_address6_to_network.<locals>.dec2binf  s9    wwU57B5KLSAXN+LMMLs   =r   z8_address6_to_network: skipping address without a netmaskr   r   Tr   z>8H      rz   r   r]   r            )rJ   r   r   r8   r!   r   r   r   r-   r.   r   r   r   r   rF   rH   r   )r1   r   r#   	orig_hostnetmaskunpackedr   ir   jr   r2   r   rN   s                 r   _address6_to_networkr	  d  s   N $HI
**S/C
3x1}M#a&$7AI!fG}}UF$4$4V__5>%@ AHG	 1X 9HQK$r 	9A!c!A$i-SU1R4Z88I	99q' 3Z *s7|qWM))G*
 g
C C1X <

3wsC(2ad2g6:;< v%{{5#a&#a&+.q63q63q6+.q63q63q6 CDG
 w''A  	  s$   F< $G <G
GGGc                    |j                  d      }t        |      dk7  st        |d   |      st        |d   }|d   }|dk(  s|dk(  ry| }d|v r9|j                  d      }t        |      dk7  st        |d   |      st        |d   }|dk(  s|dk(  ry|rt	        |      rt	        |      s"t        t        |      rt        |      st        t        ||      r|st        ||      }|rIt        |d|      j                  d      d   }t        |d|      j                  d      d   }||k(  S t        |d|      j                  d      d   }t        |d|      j                  d      d   }||k(  S )z&Determine if address x is in network yr   r   r   r   z0.0.0.0z::T)
r   r   r8   r!   r3   r9   r/   r   r	  rI   )	
tested_add
tested_netr<   r#   r  r  addressorig_networkrN   s	            r   
in_networkr    s   


3
C
3x1}M#a&"5AI!fGId!2G
g~mmC s8q=c!fb 9a&)w$	g&nY.Gg&nY.G7B')'26 
+-6-A BBG%*QP&(/(: ;;@5:aI l"" ,-6-A BBG%*QP&(/(: ;;@5:aI l""r&   c                      d} dD ]E  }t         j                  j                  |d      } t         j                  j                  |       r nd} G | dk(  rt	        t
        j                  d      | S )Nr   )z/sbinz/binz	/usr/sbinz/usr/binz/usr/local/sbinz/usr/local/biniptableszCould not find iptables)rh   r   r   existsr_   r`   ra   )r   ds     r   _find_system_iptablesr    sf    
C3  ggll1j)77>>#C byell$=>>Jr&   c                     | 
t               } t        | dg      \  }}|dk7  rt        t        j                  d| z        |j                         }t        j                  dd|d         S )zReturn iptables versionz-Vr   zError running '%s'z^vr   r   )r  r   r_   r`   ra   r   r+   sub)r   rm   rl   r#   s       r   get_iptables_versionr    sa    
{#%S$K IR	Qwell$8C$@AA
))+C66$CF##r&   c                 (   d }|r1t        j                         dk7  rt        t        j                  d      | 
t               } g }d}| j                  d      rd}|t        dd      z  }t        | d	|g      \  }}|dk7  rt        t        j                  |       || |g d
      r|j                  d        || |g d      r|j                  d       t        | d|g       t        | d|g      \  }}|dk7  rt        t        j                  |      |S )z[Return capabilities set for netfilter to support new features. Callers
       must be root.c                 <    | d|g}t        ||z         \  }}|dk(  ryy)Nz-Ar   TF)r   )r   chainruleargsrm   rl   s         r   test_capz,get_netfilter_capabilities.<locals>.test_cap  s-    T5!t$	S7r&   r   zMust be rootzufw-caps-test	ip6tableszufw6-caps-testr   )prefixdirz-N)-m	conntrack	--ctstateNEWr!  recentz--setz
recent-set)r!  r"  r#  r$  r!  r%  z--updatez	--seconds30z
--hitcountr>   zrecent-updatez-Fz-X)rh   getuidr_   r`   EPERMr  endswithr   r   ra   rF   )r   	do_checksr  capsr  rm   rl   s          r   get_netfilter_capabilitiesr,    s    RYY[A%ekk>22
{#%DE
||K   
V22&&E S$&'IR	QwellC(( U 6 7L! U 0 1 	O$ dES$&'IR	QwellC((Kr&   c                 |   t        |       }t               }|j                         D ]  }|j                  d      s|j                  d      s'|j	                         }|d   }|d   j	                  d      d   }t               }dj                  |d   j	                  d      dd       |d<   |d	   |d
<   |d   j	                  d      d   |d<   |d   dk(  r	|d   |d<   n|d   j	                  d      d   |d<   ||vrt               ||<   g ||   |<   n|||   vrg ||   |<   ||   |   j                  |        |S )z:Get and parse netstat the output from get_netstat_output()r   r   r   r   :r\   Nladdrr]   uidr  r   r   -r   )get_netstat_outputdict
splitlines
startswithr   r   rF   )r<   netstat_outputr  r   r#   r   r   items           r   parse_netstat_outputr8  '  sP    (+NA))+ $u%dooe.DjjlA1v||C $vQc!23B!78W!fU!fll3'*U;#u+DKa&,,s+A.DK>vAeHAeHTN1U8#!#%	%d#1$4 Hr&   c                    d}|rd}t         j                  j                  |      st        t        j
                  d|z        t        |      j                         D ]  }|j                         }| |d   k(  sdj                  t        dt        |d         d      D cg c]  }|d   ||dz     c}      }|d   j                         d	k7  sr|d
t        |d   j                         d      } |dk(  rt        t        j                  d      t!        j                   t         j"                  t         j$                        }	 t!        j&                  t)        j*                  |j-                         dt/        j0                  d| dd             dd       }t5        ||      d   S c c}w # t2        $ r t        t        j                  d      w xY w)zGet IP address for interfacer   /proc/net/if_inet6'%s' does not existr  r.  r   r   r   80r   r   No such devicei  256sN         )rh   r   r  r_   r`   ra   rS   r   r   r   r   r   r   r   r   ENODEVr   r6   
SOCK_DGRAMr   fcntlioctlre   r   r   r   rP   )ifnamer<   r1   procr   r#   r  r   s           r   get_ip_from_ifrH  M  s   D 
#ww~~d#%,,(=(DEEJ((* 	ED**,CQxx38CAK3KLaCF1QqSMLN q6<<>T)&*CA,CDD	E 2:%,,(899MM&..&*;*;<	:##EKK
F$*KKs$D%FFH%M ND
 T2&q)) M  	:%,,(899	:s   F&
AF+ +$Gc           
         d}d}t        |       rd}d}n%t        |       st        t        j                  d      t
        j                  j                  |      st        t        j                  d|z        d}|rt        |      j                         D ]  }|j                         }|d   j                         }d	j                  t        d
t!        |d
         d      D cg c]  }|d
   ||dz     c}      }|d   j#                         dk7  r"|dt%        |d   j#                         d      }| |k(  sd|v st'        | |d      s|} |S  |S t        |      j                         D ]@  }d	|vr|j                  d	      d
   j                         }	 t)        |d      }	|	| k(  s=|} |S  |S c c}w # t        $ r Y Uw xY w)zGet interface for IP addressFz/proc/net/devTr:  r=  r;  r   r  r.  r   r   r   r<  r   r   )r3   r9   r   r`   rB  rh   r   r  r_   ra   rS   r   r   stripr   r   r   r   r   r  rH  )
r1   r<   rG  matchedr   r#   rF  r  tmp_addrips
             r   get_if_from_iprN  m  s   	BDd#D!ell$45577>>$ell$9D$@AAG	J((* 	D**,CV\\^Fxx38CAK3KLaCF1QqSMLNH1v||~%&.CFLLNB0GHxxJtXt$D   N9	8 N J((* 	D$ZZ_Q'--/F#FE2 Tz N	 N/ M   s   F.
F33	F?>F?c                  2   t        j                  d      } | j                          t        j                  d      }t               }| D ]  }|j                  |      st         j                  j                  d|d      }t        j                  |t         j                  t         j                  z        smd}	 t        j                  t         j                  j                  d|d            }	 t        j                  |      }|D ]`  }	 t        j                  t         j                  j                  ||            d   }|dt         j                  j                  |      ||<   b ! |S # t        $ r Y w xY w# t        $ r Y ?w xY w# t        $ r Y w xY w)zGet inodes of files in /procr   r   rk   r1  r   r   r   )rh   listdirr   r+   compiler3  r,   r   r   accessF_OKR_OKreadlinkr   r   basename)	
proc_filespatinodesr  fd_pathexe_pathdirsr  inodes	            r   _get_proc_inodesr^    sZ   G$JOO
**[
!CVF Fyy|'',,w40 yy"''BGG"34	{{277<<E#BCH	::g&D  	FAWa 89!< ()"''*:*:8*DEF5M	F+F8 M  		
  		  s6   74E+,E:6F
+	E76E7:	FF
	FFc                 l   ddddddddd	d
dd}ddddd}t         j                  j                  d|       }t        j                  |t         j                  t         j
                  z        st        g }d}t        |      j                         }|D ]  }|j                         }|sd}|t        ||d      d         }	| j                  d      rd}	n| j                  d      r|	d
k7  rX||d      j                  d      \  }
}||d      }||d      }|j                  |
t        |d      |||	f        |S )z=Read /proc/net/(tcp|udp)[6] file and return a list of tuples ESTABLISHEDSYN_SENTSYN_RECV	FIN_WAIT1	FIN_WAIT2	TIME_WAITCLOSE
CLOSE_WAITLAST_ACKLISTENCLOSING)r   r   r]   r   r  r  r  r   	   
      r   r]   r  rk  )
local_addrstater0  r]  z	/proc/netFTro  r   r   NAr   rn  r.  r0  r]  )rh   r   r   rR  rS  rT  r!   rS   r   r   r   r5  rF   )protocol
tcp_statesproc_net_fieldsrT   r   skipped_firstlinesr   fieldsro  r/  r   r0  r]  s                 r   _read_proc_net_protocolrw    s]   #  !!!"  J '(!" !"O 
k8	,B99R277*+
CMH E > M3vog&>?DEu%E  'EX,=_\:;AA#Ft_U+,w/0

E3tR=#ue<=> Jr&   c                 X   d}t        |       dkD  rd}t        ddd      D ]8  }|dj                  t        |dz   |d      D cg c]
  }| |dz
  |  c}      z  }: t        dj                  t        dt        |      d      D cg c]  }|||dz    j	                          c}      d	      d   }|S g }t        ddd      D cg c]
  }| |dz
  |  c}D ]&  }|j                  t        t        |d
                   ( t        dj                  |      d      d   }|S c c}w c c}w c c}w )zDConvert an address from /proc/net/(tcp|udp)* to a normalized addressr   r   r   r   r   r.  r   Tr   r   F)r   r   r   rP   r   rF   r   r   )paddr	convertedr#   r  r  s        r   convert_proc_addressr|    s2   I
5zA~q"a 	HA27751a3DFaU1Q3q\FGGC	H%chh,1!SXq,ABqAac
  "B'D	  ).q!R:A51Q<: 	(AJJs3q":'	(%chhsmU;A>	 GB ;s   DD"D'c                    t               }ddg}| r|ddgz  }|D ]  }	 t        |      ||<    t               }t        |j                               }|j                          d}|D ][  }||   D ]Q  \  }}	}
}}t        |      }d}t        |      |v r|t        |         }||dd	|d
|	dd	|dd	|
dd	|dd	|dz  }S ] |S # t        $ r t        d|z        }t	        |       Y w xY w)z5netstat-style output, without IPv6 address truncationr   r   tcp6udp6z!Could not get statistics for '%s'r   r1  5r   r.  4611r   )r3  rw  r   r    r*   r^  listkeysr   r|  r   )r<   proc_net_datar   pr   rY  	protocolsr   r/  r   r0  r]  ro  r1   r   s                  r   r2  r2    s$   FMENE	&&!! 	6q9M! F]'')*INN
A 
O0=a0@ 		O,UD#ue'.DC5zV#SZ(qBF7M7<c5#O OA		O
O H/  	<BCHN	s   C"C*)C*c                     || S | j                  d      r7t        |       dk  r|}|S t        j                  j	                  || dd       }|S t        j                  j	                  ||       }|S )zAdd prefix to dirNr   r   r   )r5  r   rh   r   r   )r   r  newdirs      r   	_findpathr  &  sm    ~

~~cs8a<F
 M WW\\&#ab'2F M fc*Mr&   c                     t         j                  d   dk  rt        j                  | d      S t	        j
                  | j                  dd            j                  d      S )z,Take a string and convert it to a hex stringr   r]   hexr   r   )errorsr^   )rc   rg   codecsr   binasciihexlifydecode)r   s    r   
hex_encoder  4  sQ    
Q}}Q&& AHHWXH>?FFwOOr&   c                     t         j                  d   dk  r!| j                  d      j                  d      S t        j                  dt        |       dz  r| dd	 n| z        j                  dd
      S )z,Take a hex string and convert it to a stringr   r]   r  )encodingr   r   r   Nr\   backslashreplace)rc   rg   r  r  	unhexlifyr   )hs    r   
hex_decoder  =  sn    
Qxxx'..w77 dA
afBCJJ# r&   c                 n    d}|s0t        | d      }t        j                  |t        j                         |S )zCreate a blocking lockfileNw)rS   rD  lockfLOCK_EX)lockfiledryrunlocks      r   create_lockr  L  s-    DHc"D%--(Kr&   c                     | y	 t        j                  | t         j                         | j                          y# t        $ r Y yw xY w)z(Free lockfile created with create_lock()N)rD  r  LOCK_UNrY   r!   )r  s    r   release_lockr  U  s>    |D%--(

  	s   4: 	AA)r   )Tr   )NT)F)z/run/ufw.lockF)I__doc__
__future__r   r  r  r`   rD  r   r   rh   r+   rp   r   r   r{   rc   	functoolsr   tempfiler   r   r   rb   supported_protocolsr   ipv4_only_protocolsr   r%   r3   r9   r8   rA   rP   rU   rZ   rn   rv   r   r   r   r   r*   rd   r   rJ   r   r   r   getpidr   r   r/   r7   rG   r   rI   r	  r  r  r  r,  r8  rH  rN  r^  rw  r|  r2  r  r  r  r  r   r&   r   <module>r     sv   (" &     	  	 	     
  $	
 Q A v& 4(42F	4n

LG2%	&* JJ 
H 299; . "))+ !N	2$\: (F7(t,#h	$6r#L*@,^"J,^& FP
r&   