
@Pc        	   @   s  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 i  Z d   Z	 d d  Z
 d d  Z d   Z d   Z d   Z d	   Z d
   Z d   Z d d d  Z d d d  Z d d d d  Z d   Z d d d d d  Z d   Z d   Z d   Z d d d d d  Z d d  Z d d  Z d d d d d  Z d d d  Z d d d d d d g  d  Z d d d d d d d g  d  Z  d   Z! d d  Z" d    Z# d!   Z$ d"   Z% d d#  Z& d$   Z' d%   Z( d S(&   iNc         C   s<   t  j |  d   } | d  k r8 t j |   t  |  <} n  | S(   N(   t	   statcachet   gett   Nonet   ost   lstat(   t   patht   ret(    (    s	   jk_lib.pyt   cachedlstat+   s    i    c         C   s  y t  |   } Wn9 t k
 rK | d k rG t j j d |  d  n  d SXt j d d k r | t j d k s | t j t	 j
 d  j k r t j j d |  d	  d SnB | t j d k s | t j d k r t j j d |  d
  d S| t j t j @s| t j t j @rMt j | t j  rMt j j d |  d  d St j | t j  st j | t j  rt j |   } | G|  GH| d  d k rt j j d |  d  d Sqt j j d |  d  d Sn  d S(   Ni    s   ERROR: cannot lstat() s   
iit   bsdt   wheels   ERROR: s    is not owned by root:wheel!
s    is not owned by root:root!
s     is writable by group or others!ii   s   usr/s2    is a symlink, please point to the real directory
is    is not a directory!
i   (   R   t   OSErrort   syst   stderrt   writet   platformt   statt   ST_UIDt   ST_GIDt   grpt   getgrnamt   gr_gidt   ST_MODEt   S_IWOTHt   S_IWGRPt   S_ISLNKt   S_ISDIRR   t   readlink(   R   t	   failquiett   statbuft   target(    (    s	   jk_lib.pyt   path_is_safe=   s4    2&?	c         C   s   t  j j |   }  t |  |  } | d k  r1 | Sx5 d D]- } t |  d
 | d  } | d k  r8 | Sq8 Wt  j j |   } xA | d
 k r t | d  } | d k r | St  j j |  } q~ Wd S(   s]   tests if path is a safe jail, not writable, no writable /etc/ and /lib, return 1 if all is OKit   etct   usrt   vart   bint   devt   proct   sbinR   t   /i   i    (   R   R    s   vars   binR#   R$   R%   s   sys(   R   R   t   abspathR   t   dirname(   R   R   t   retvalt   subdt   npath(    (    s	   jk_lib.pyt   chroot_is_safe]   s    c         C   s/   t  |   } | t j t j t j B@r+ d Sd S(   sA   returns 1 if the file is setuid or setgid, returns 0 if it is noti   i    (   R   R   R   t   S_ISUIDt   S_ISGID(   R   R   (    (    s	   jk_lib.pyt   test_suid_sgidq   s    c      
   C   sM   t  j d  d k rI t |  d d d d d d d d t j d |   n  d  S(	   Ni   t   linuxs   /etci    t   copy_permissionst
   allow_suidt   copy_ownerships   ldconfig -r (   R   R   t   create_parent_pathR   t   system(   t   jail(    (    s	   jk_lib.pyt   gen_library_cachex   s    "c         C   s  g  } t  j d |  d t d t  j d t  j d t  j d t } | j j   } xt |  d k rt j |  } t |  d k r| d d k r | d	 d
 k r | S| d d k r | d d k r | d d k r | S| d d k s| d d k r qt |  d k r5| d d k r5| d d k r5qt |  d k rt	 j
 j | d  rq| | d g 7} qd | d d |  GHqt |  d	 k r| d d d k rt	 j
 j | d  r| | d g 7} qd | d GHqd | d  GHn d | d  GH| j j   } qR W| S(   s;   returns a list of libraries that the executable depends on s   ldd t   shellt   stdint   stdoutR   t	   close_fdsi    t
   staticallyi   t   linkedt   noti   t   dynamici   t
   executables   linux-gate.so.1s   linux-vdso.so.1i   t   founds!   ldd returns non existing library s    for R&   s$   WARNING: failed to parse ldd output i(   t
   subprocesst   Popent   Truet   PIPER:   t   readlinet   lent   stringt   splitR   R   t   exists(   R@   R)   t   pt   linet   subl(    (    s	   jk_lib.pyt   lddlist_libraries_linux~   s4    : 0 2&c         C   s  g  } d } t  j d |  d t d t  j d t  j d t  j d t } | j j   } x^t |  d k rt j |  } t |  d k r| d |  d	 k r q| d d
 k r t |  d k r| d d k rd } qqt |  d k r| d k r8t	 j
 j | d  r(| | d g 7} qd | d GHq| d k r~t	 j
 j | d  rn| | d g 7} qd | d GHqd GHqd | d  GHn d | d  GH| j j   } qX W| S(   s;   returns a list of libraries that the executable depends on i   s   ldd R8   R9   R:   R   R;   i    t   :t   Starti   i   t   Namei   i   s!   ldd returns non existing library s1   unknown mode, please report this bug in jk_lib.pys$   WARNING: failed to parse ldd output i(   RB   RC   RD   RE   R:   RF   RG   RH   RI   R   R   RJ   (   R@   R)   t   modeRK   RL   RM   (    (    s	   jk_lib.pyt   lddlist_libraries_openbsd   s6    :"	c         C   s  g  } t  j d |  d t d t  j d t  j d t  j d t } | j j   } xEt |  d k rt j |  } t |  d k rRt |  d k r | d t |   d  |  d	 k r qt |  d
 k r | d d k r | d d k r | St |  d k r>t	 j
 j | d  r.| | d g 7} qOd | d GHqd | d  d GHn2 | t |   d  |  d	 k rsn d | d  d GH| j j   } qR W| S(   s;   returns a list of libraries that the executable depends on s   ldd R8   R9   R:   R   R;   i    i   RO   i   i   R>   i   R?   s!   ldd returns non existing library s%   WARNING: failed to parse ldd output "it   "(   RB   RC   RD   RE   R:   RF   RG   RH   RI   R   R   RJ   (   R@   R)   RK   RL   RM   (    (    s	   jk_lib.pyt   lddlist_libraries_freebsd   s(    :42c         C   s   t  j d  d k r t |   St  j d  d k r: t |   St  j d  d k rW t |   St  j d  d k r t |   } | d g 7} | St |   } | d d	 d
 g 7} | Sd  S(   Ni   R0   i   t   openbsdt   freebsdt   sunoss   /lib/ld.so.1s   /usr/libexec/ld.sos   /usr/libexec/ld-elf.so.1s   /libexec/ld-elf.so.1(   R   R   RN   RS   RU   (   R@   R)   (    (    s	   jk_lib.pyt   lddlist_libraries   s    


t    c         C   sf  |  d k r d St  |   } d } | s? | d } | d  } n  d } d } x| D] } t j j | |  } t |  } t j | j  rR | d 7} t j |  }	 |	 d d k r t j j	 | |	  } qOt j j	 t j j t j j
 |  |	   }
 t |  d k rF|
 t |   | k rFt j j d |
 d  t d  n  |
 } qR qR Wt j j | |  S(	   NR&   RZ   ii    i   s   ERROR: symlink s    points outside jail, ABORT
s   Symlink points outside jail(   t
   split_pathR   R   t   joinR   R   R   t   st_modeR   t   normpathR(   RG   R   R   R   t	   Exception(   R   t   chroott   include_filet   spatht   basenameR   t
   doscountert   entryt   sbt   realpatht   tmp(    (    s	   jk_lib.pyt   resolve_realpath   s.    

-(c   
      C   s  t  |  } | r! d } |  } n$ t j j |   } t j j |   } d } x5| d k r| d k rt |  } t j | j  rM| d 7} t j	 |  } | d d k r | | } | d d k rJ| d  } qJqyt j j
 t j j t j j |  |   }	 | d k rD|	 |  | k rDt j j d |	 d  t d	  n  |	 } n, t j j |  d | } t j j |  } d
 } qN Wd | S(   sN   will return the same path that contains not a single symlink directory elementRZ   i    R&   id   i   is   ERROR: symlink s    points outside jail, ABORT
s   Symlink points outside jailN(   RG   R   R   Rc   R(   R   R   R   R]   R   R^   R\   R   R   R   R_   R   (
   R   R`   Ra   t	   chrootlent   donepatht   todopathRd   Rf   Rg   Rh   (    (    s	   jk_lib.pyt   OLDresolve_realpath  s2    	

-	
c         C   s   t  j |   } t j | t j  } | sd | t j t j B@rd d | GH| t j @t j @} qd n  t  j | | t j | t j f  | r t  j	 | | t j
 | t j  n  t  j | |  d  S(   Ns,   removing setuid and setgid permissions from (   R   R   t   S_IMODER   R-   R.   t   utimet   ST_ATIMEt   ST_MTIMEt   chownR   R   t   chmod(   t   srct   dstt
   be_verboseR2   R3   t   sbufRR   (    (    s	   jk_lib.pyt   copy_time_and_permissions5  s    	$$c         C   sO   |  } xB t  j j |  rJ | d k p1 | d k rJ t  j j |  } q	 W| S(   ss   This function tests if a directory exists, if not tries the parent etc. etc. until it finds a directory that existsR&   RZ   (   R   R   RJ   R(   (   R   Rh   (    (    s	   jk_lib.pyt!   OLDreturn_existing_base_directoryJ  s    /i   c         C   s}  | } | d d k r# | d  } n  y- t  |  | |   } t j j |  rO d SWn t | |	  k
 rl n Xt |  |  }
 t |
  t |   } t j | d | d  } | d k r t |  } n  x| d k rx| d | k r | } n7y t	 | |   } Wn> t k
 rC\ } }	 t
 j j d | |  d |	 d  Pn Xt j | j  rct j | |   } t  |  | |  |   } | rd | d	 | GHn  y t j | |  WnH t k
 r\ } }	 | d
 k rqt
 j j d |  | |  d  n X| d d k r%t |  | | | | |  q t j | |  d  } t |  | | d  | | | | |  n t j | j  r t  |  | |  |   } | rd | GHn  t j | d  | r y t | |  | | | |  Wqt k
 r\ } }	 t
 j j d | |  d	 | d |	 d  qXq n  | } | t |  k rAd } q t j | d | d  } | d k r t |  } q q Wd S(   su   creates the directory and all its parents id needed. copy_ownership can only be used if copy permissions is also usediR&   Ni   s   ERROR: failed to lstat(s   ):s   
s   Creating symlink s    to i   s    ERROR: failed to create symlink i    s   Creating directory i  s2   ERROR: failed to copy time/permissions/owner from s   : (   Ri   R   R   RJ   R
   t   return_existing_base_directoryRG   RH   t   findR   R   R   R   R   R   R]   R   t   symlinkR4   t   rfindR   t   mkdirRx   (   R`   R   Rv   R1   R2   R3   t	   directoryt   chrootdirectoryt   errnot   strerrorRh   t   oldindxt   indxRf   t   realfilet
   chrootnamet   indx2(    (    s	   jk_lib.pyt   OLD_create_parent_pathQ  sj    	$$(6	c         C   sa   d } d } xN |  D]F } | d k s1 | d k r> | | 7} n  | d k rS d } q d } q W| S(   NRZ   i    R&   i   (    (   t   instringt	   outstringt   slasht   i(    (    s	   jk_lib.pyt   fix_double_slashes  s    	
c         C   sc   g  } t  t j j |    } x> | d k r^ | j d t j j |   t j j |  } q! W| S(   NR&   i    (   R   R   R   R^   t   insertRc   R(   (   R   R   t   next(    (    s	   jk_lib.pyR[     s    c         C   s?   t  |   d k r d Sd } x |  D] } | d | 7} q# W| S(   Ni    R&   RZ   (   RG   (   Rb   R   Re   (    (    s	   jk_lib.pyt	   join_path  s    c         C   s  t  |  } |  } d } x} | t |  k  r t j j | | |  }	 t j j |	  s\ Pn  t |	 |  d  }
 t j j |
  s Pn  |
 } | d 7} q Wxe| t |  k  rt | d | d ! } t j j | | |  } y t |  } Wn: t	 k
 r)\ } } t
 j j d | d | d  d  SXt j | j  r| rNd | GHn  t j | d  | ry t | | | | |  Wqt	 k
 r\ } } t
 j j d t t  d	 t d
 | d  qXqn t j | j  rt j |  } | rd | d	 | GHn  t j | |  | d d k rEt |  | | | | |  } qt j j t j j t j j |  |   }
 t |   d k r|
 t |    |  k rt
 j j d |
 d  t d  n  |
 t |   } t |  | | | | |  } n  | } | d 7} q W| S(   Ni    i   s   ERROR: failed to lstat(s   ):s   
s   Create directory i  s2   ERROR: failed to copy time/permissions/owner from s    to s   : s   Creating symlink R&   s   ERROR: symlink s    points outside jail, ABORT
s   Symlink points outside jail(   R[   RG   R   R   R\   RJ   Ri   R   R   R
   R   R   R   R   R   R   R]   R~   Rx   R   R   R   R   R   R|   R4   R^   R(   R_   (   R`   R   Rv   R1   R2   R3   Rb   t	   existpathR   t   tmp1Rh   t   origpatht   jailpathRf   R   R   R   (    (    s	   jk_lib.pyR4     sZ     6-(c   	   
   C   s  y? | r d | GHn  t  j |  t |  | | d d d d WnH t t f k
 r \ } } t j j d |  d | d | d	  d SXx7t  j |   D]&\ } } } x | D] } | r d
 | d | d | d | GHn  yP t	 j
 | d | | d |  t | d | | d | | d d d d Wq t t f k
 r\ } } t j j d | d | d | d | d | d	  d SXq Wx. | D]& } t | d | | d | |  qWq Wd S(   Ns   Creating directoryR2   i    R3   i   s)   ERROR: copying directory and permissions s    to s   : s   
s   Copying R&   s$   ERROR: copying file and permissions (   R   R~   Rx   t   IOErrorR
   R   R   R   t   walkt   shutilt   copyfilet#   move_dir_with_permissions_and_owner(	   t   srcdirt   dstdirRv   R   R   t   roott   dirst   filest   name(    (    s	   jk_lib.pyt#   copy_dir_with_permissions_and_owner  s*     ($ 08	(c         C   s   t  |  | |  } | d k r | d k r6 d |  GHn  y t j |   Wq t t f k
 r \ } } t j j d |  d | d  q Xn d | d |  GHd  S(   Ni   s!   Removing original home directory s   ERROR: failed to remove s   : s   
s   Not everything was copied to s   , keeping the old directory (   R   R   t   rmtreeR
   R   R   R   R   (   R   R   Rv   R)   R   R   (    (    s	   jk_lib.pyR     s    'c   	      C   s   d } | d k rN y t  j |  |  d } WqN d |  d | d GHqN Xn  | d k r y0 t j |  |  t |  | | d | d | Wq t t f k
 r \ } } t j j	 d |  d | d	 | d
  q Xn  d S(   sX   copies/links the file and the permissions (and possibly ownership and setuid/setgid bitsi   i    s   Linking s    to s    failed, will revert to copyingR2   R3   s$   ERROR: copying file and permissions s   : s   
N(
   R   t   linkR   R   Rx   R   R
   R   R   R   (	   Rt   Ru   Rv   t   try_hardlinkR2   t   retain_ownert   do_normal_copyR   R   (    (    s	   jk_lib.pyt   copy_with_permissions  s    
 c   
   
   C   s  t  |  t j j |  | d d d d d d t |  | |   } t j j |  rd d | d GHd  St j |  } yXt j d  d	 k r | j	 d
 } | j	 d
 } nr t j d k r t j
 d k r | j	 d } | j	 d } q| j	 d } | j	 d } n | j	 d
 } | j	 d
 } t j | j  r3d } n, t j | j  rNd } n d | d GHd S| d k r{d |  | GHn  t j t j d d | t |  t |  t |   }	 t | | d d d | Wn3 d | d GHd | d GHd | d GHd GHn Xd  S(   NR1   i   R2   i    R3   s   Device s    does exist alreadyi   R0   i   t   sunos5ii   t   ct   bs	   WARNING, s#    is not a character or block devices   Creating device t   mknods   Failed to create device s(   , this is a know problem with python 2.1s   use "ls -l s6   " to find out the mode, major and minor for the devices   use "mknod s'    mode major minor" to create the devices<   use chmod and chown to set the permissions as found by ls -l(   R4   R   R   R(   Ri   RJ   R   R   R   t   st_rdevt   maxintt   S_ISCHRR]   t   S_ISBLKt   spawnlpt   P_WAITt   strRx   (
   R`   R   Rv   R   t
   chrootpathRf   t   majort   minorRR   R   (    (    s	   jk_lib.pyt   copy_device!  sB    .		6c	         C   s   d	 }	 x t  j |  D] }
 t  j j | |
  } y t |  } t j | j  r t |  | d | d d d | d | t	 |  | | | | | | | | 	 } n |	 t  j j | |
  f 7}	 Wq t
 k
 r } t j j d | d | j d  q Xq Wt |  |	 | | | | | | | 	 } | S(
   sb   copies a directory and the permissions recursively, possibly with ownership and setuid/setgid bitsRv   R1   i   R2   R3   s)   ERROR: failed to investigate source file s   : s   
(    (   R   t   listdirR   R\   R   R   R   R]   R4   t   copy_dir_recursiveR
   R   R   R   R   t   copy_binaries_and_libs(   R`   t   dirt   force_overwriteRv   t
   check_libsR   R2   R   t   handledfilest   files2Re   Rh   Rw   t   e(    (    s	   jk_lib.pyR   I  s    %' +$c
         C   s  |  d d k r |  d  }  n  xu| D]m}
 |
 |	 k r< q$ n  y t  |
  } Wn t k
 r(} | j d k r | d k r t j |
  } t |  d k r t |  | | | | d | d | d d d	 |	 }	 q | r d
 |
 d GHq q"| r"d |
 d GHq"q$ t j j d |
 d | j	 d  q$ n Xt
 |  t j j |
  | d d d | d | t t j j |  d |
  |   } y t  |  } d } WnR t k
 r} | j d k rd } qt j j d |  |
 d | j	 d  n X| d k r#| r#t j | j  r#| rd | d GHqq$ | r
| rt j | j  r| rWd | d GHn  y t j |  Wqt k
 r} t j j d |  t d | j	 d |  t d  qXqt j | j  rd | d GHqq
t j | j  rq
| r$ d | d GHq$ q$ n  t
 |  t j j |
  | d d d | d | t j | j  r	t j |
  } y% d | d | GHt j | |  Wn t k
 rn X|	 j |
  | d d k rt j j t j j t j j |
  |   } n  t |  | g | | | | | | |	 	 }	 n t j | j  rBt |  |
 | | | | | | |	 	 }	 n t j | j  r| rnd |
 d | GHn d  |
 d | GHt |
 | | | | |  |	 j |
  nR t j | j  st j | j  rt |  |
 | |  n t j j d! |
 d"  t j  | t j!  } | r$ t" j# |
 d#  d k sat" j# |
 d$  d k sa| t j$ t j% Bt j& B@r$ t' |
  } t |  | | | d | d	 |	 }	 q$ q$ W|	 S(%   s>   copies a list of executables and their libraries to the chrootiR&   i   i   i    R   R   t   try_glob_matchingR   s   Source file(s) s    do not exists   Source file s    does not exists)   ERROR: failed to investigate source file s   : s   
R1   R2   R3   s.   ERROR: failed to investigate destination file RZ   s"    already exists, will not touch its   Destination file s$    exists, will delete to force updates   ERROR: failed to delete s   
cannot force update s   Destination dir s    existss   Creating symlink s    to s   Trying to link s   Copying s   Failed to find how to copy s=    into a chroot jail, please report to the Jailkit developers
t   libs   .so((   R   R
   R   t   globRG   R   R   R   R   R   R4   R   R   R(   Ri   R^   R   R   R]   t   S_ISREGt   unlinkt   rfileR   R   R|   t   appendR\   R   R   R   R   R   Rn   R   RH   R{   t   S_IXUSRt   S_IXGRPt   S_IXOTHRY   (   R`   t   binarieslistR   Rv   R   R   R2   R   R   R   t   fileRf   R   R   t   chrootrfilet   chrootsbt   chrootfile_existsR   RR   t   libs(    (    s	   jk_lib.pyR   j  s    3#.#
	+%:.0*'$Q(c         C   sd   g  } |  j  | |  r` |  j | |  } x3 t j | d  D] } | t j |  g 7} q= Wn  | S(   s   retrieves a comma separated option from the configparser and splits it into a list, returning an empty list if it does not existt   ,(   t
   has_optionR   RH   RI   t   strip(   t	   cfgparsert   sectionnamet
   optionnameR)   t   inputstrRh   (    (    s	   jk_lib.pyt   config_get_option_as_list  s    t   ERRORc         C   s*   d GH| d | GH|   t  j |   d  S(   NRZ   s   : (   R   t   exit(   t   exitnot   messaget	   usagefunct   type(    (    s	   jk_lib.pyt
   clean_exit  s    c         C   s   y t  | d  } Wn d SX| j   } xd t |  d k r t j | d  } t |  | k r | | |  k r | j   d S| j   } q- Wd S(   Nt   ri    RO   i   (   t   openRF   RG   RH   RI   t   close(   t   itemt   numt   filenamet   fdRL   t   pwstruct(    (    s	   jk_lib.pyt   test_numitem_exist  s    "
c         C   s   t  |  d |  S(   Ni    (   R   (   t   usert
   passwdfile(    (    s	   jk_lib.pyt   test_user_exist  s    c         C   s   t  |  d |  S(   Ni    (   R   (   t   groupt	   groupfile(    (    s	   jk_lib.pyt   test_group_exist  s    c   	   
   C   s  |  d d k r |  d  }  n  t  |  d | d d d d d d t j d d	 !d
 k r t |  d d  j   t |  d d  j   t |  d d  j   t |  d d  j   nDt j j |  d  s t |  d d  } nt |  d d  } | j   } x t	 |  d k rt
 j | d  } t	 |  d k r| d | k sX| d | k r| rzd | d d |  d GHn  y | j | d  Wn t k
 rn Xy | j | d  Wqt k
 rqXqn  | j   } qW| j d d  t	 |  d k rt d d  } | j   } x t	 |  d k rt
 j | d  } t	 |  d k r| d | k sx| d | k r| j |  | rd | d d |  d GHn  | d | k r| | d g 7} qqn  | j   } q"W| j   n  | j   t j j |  d  s$t |  d d  } nt |  d d  } | j   } x t	 |  d k r%t
 j | d  } t	 |  d k r| d | k s| d | k r| rd | d d |  d GHn  y | j | d  Wn t k
 rn Xy | j | d  Wqt k
 rqXqn  | j   } qFW| j d d  t	 |  d k rt d d  } | j   } x t	 |  d k r t
 j | d  } t	 |  d k r| d | k s| d | k r| j |  | rd | d d |  d GHqqn  | j   } qfW| j   n  | j   d  S(   NiR&   s   /etc/R1   i    R2   R3   i   i   R   s   /etc/passwdt   as   /etc/spwd.dbs   /etc/pwd.dbs   /etc/master.passwdt   ws   r+RO   i   i   s   user s    exists in R   s   writing user s    to s
   /etc/groups   group s   writing group (   R4   R   R   R   R   R   R   t   isfileRF   RG   RH   RI   t   removet
   ValueErrort   seekR   (	   R`   t   userst   groupsRv   t   fd2RL   R   R   t   groupstruct(    (    s	   jk_lib.pyt   init_passwd_and_group  s    " 
 
 
 "c         C   sm   t  j d  } t j | d  } xE | D]= } t  j j | |   } t  j j |  r( t  j j |  Sq( Wd  S(   Nt   PATHRO   (	   R   t   getenvRH   RI   R   R\   RJ   R'   R   (   R   t   search_patht   pathsR   t   joined(    (    s	   jk_lib.pyt   find_file_in_pathE  s    c         C   s]   g  } xP |  D]H } | d d k r3 | j  |  q t |  } | r | j  |  q q W| S(   Ni    R&   (   R   R   (   R   t   paths2Rh   t   tmp2(    (    s	   jk_lib.pyt   find_files_in_pathN  s    ()   t   os.pathR   RH   R   R   R   R   RB   R    R   R   R,   R/   R7   RN   RS   RU   RY   Ri   Rm   Rx   Ry   R   R   R[   R   R4   R   R   R   R   R   R   R   R   R   R   R   R   R   R   (    (    (    s	   jk_lib.pyt   <module>    sN   	 			&	&		 	A			<(!!c					S		