2022-10-18 20:36:59 +00:00
#!/usr/bin/python3 -EsI
2013-01-11 19:23:09 +00:00
# Copyright (C) 2012 Red Hat
# AUTHOR: Dan Walsh <dwalsh@redhat.com>
# see file 'COPYING' for use and warranty information
#
# semanage is a tool for managing SELinux configuration files
#
# 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, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
#
2015-07-24 08:07:13 +00:00
import os
import sys
2013-10-11 14:16:57 +00:00
import selinux
import sepolicy
2019-10-18 09:20:05 +00:00
from multiprocessing import Pool
2013-10-11 14:16:57 +00:00
from sepolicy import get_os_version , get_conditionals , get_conditionals_format_text
2013-01-11 19:23:09 +00:00
import argparse
2022-04-01 09:57:24 +00:00
PROGNAME = " selinux-python "
2013-01-11 19:23:09 +00:00
try :
2016-08-04 18:34:02 +00:00
import gettext
kwargs = { }
if sys . version_info < ( 3 , ) :
kwargs [ ' unicode ' ] = True
2022-05-06 14:06:23 +00:00
t = gettext . translation ( PROGNAME ,
2013-01-11 19:23:09 +00:00
localedir = " /usr/share/locale " ,
2022-06-24 14:24:25 +00:00
* * kwargs ,
fallback = True )
2022-05-06 14:06:23 +00:00
_ = t . gettext
2016-08-04 18:34:02 +00:00
except :
try :
import builtins
builtins . __dict__ [ ' _ ' ] = str
except ImportError :
import __builtin__
__builtin__ . __dict__ [ ' _ ' ] = unicode
2013-01-11 19:23:09 +00:00
2013-10-11 14:16:57 +00:00
usage = " sepolicy generate [-h] [-n NAME] [-p PATH] [ "
2015-07-24 08:07:13 +00:00
usage_dict = { ' --newtype ' : ( ' -t [TYPES [TYPES ...]] ' , ) , ' --customize ' : ( ' -d DOMAIN ' , ' -a ADMIN_DOMAIN ' , " [ -w WRITEPATHS ] " , ) , ' --admin_user ' : ( ' [-r TRANSITION_ROLE ] ' , " [ -w WRITEPATHS ] " , ) , ' --application ' : ( ' COMMAND ' , " [ -w WRITEPATHS ] " , ) , ' --cgi ' : ( ' COMMAND ' , " [ -w WRITEPATHS ] " , ) , ' --confined_admin ' : ( ' -a ADMIN_DOMAIN ' , " [ -w WRITEPATHS ] " , ) , ' --dbus ' : ( ' COMMAND ' , " [ -w WRITEPATHS ] " , ) , ' --desktop_user ' : ( ' ' , " [ -w WRITEPATHS ] " , ) , ' --inetd ' : ( ' COMMAND ' , " [ -w WRITEPATHS ] " , ) , ' --init ' : ( ' COMMAND ' , " [ -w WRITEPATHS ] " , ) , ' --sandbox ' : ( " [ -w WRITEPATHS ] " , ) , ' --term_user ' : ( " [ -w WRITEPATHS ] " , ) , ' --x_user ' : ( " [ -w WRITEPATHS ] " , ) }
2013-10-11 14:16:57 +00:00
2013-01-11 19:23:09 +00:00
class CheckPath ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
if not os . path . exists ( values ) :
2015-07-24 08:07:13 +00:00
raise ValueError ( " %s does not exist " % values )
2013-01-11 19:23:09 +00:00
setattr ( namespace , self . dest , values )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
class CheckType ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
2015-07-24 08:07:13 +00:00
if isinstance ( values , str ) :
2013-01-11 19:23:09 +00:00
setattr ( namespace , self . dest , values )
else :
newval = getattr ( namespace , self . dest )
if not newval :
newval = [ ]
for v in values :
newval . append ( v )
setattr ( namespace , self . dest , newval )
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
class CheckBoolean ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
booleans = sepolicy . get_all_booleans ( )
newval = getattr ( namespace , self . dest )
if not newval :
newval = [ ]
2015-07-24 08:07:13 +00:00
if isinstance ( values , str ) :
2013-10-11 14:16:57 +00:00
v = selinux . selinux_boolean_sub ( values )
if v not in booleans :
raise ValueError ( " %s must be an SELinux process domain: \n Valid domains: %s " % ( v , " , " . join ( booleans ) ) )
newval . append ( v )
setattr ( namespace , self . dest , newval )
else :
for value in values :
v = selinux . selinux_boolean_sub ( value )
if v not in booleans :
raise ValueError ( " %s must be an SELinux boolean: \n Valid boolean: %s " % ( v , " , " . join ( booleans ) ) )
newval . append ( v )
setattr ( namespace , self . dest , newval )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
class CheckDomain ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
2013-10-11 14:16:57 +00:00
domains = sepolicy . get_all_domains ( )
2013-01-11 19:23:09 +00:00
2015-07-24 08:07:13 +00:00
if isinstance ( values , str ) :
python: replace aliases with corresponding type names
Aliases are not used in the selinux database. When user enters a type
alias as a parameter it should be converted to the corresponding type
in order to be processed correctly further in the userspace logic.
Fixes e.g.:
\#sepolicy transition -s phpfpm_t
/* where phpfpm_t is a type alias of httpd_t */
Traceback (most recent call last):
File "/usr/bin/sepolicy", line 691, in <module>
args.func(args)
File "/usr/bin/sepolicy", line 458, in transition
mytrans = setrans(args.source, args.target)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 48, in __init__
self._process(self.source)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 54, in _process
trans = _get_trans(source)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 36, in _get_trans
src_list = [src] + list(filter(lambda x: x['name'] == src, sepolicy.get_all_types_info()))[0]['attributes']
IndexError: list index out of range
2018-10-30 15:26:29 +00:00
values = sepolicy . get_real_type_name ( values )
if values not in domains :
2013-01-11 19:23:09 +00:00
raise ValueError ( " %s must be an SELinux process domain: \n Valid domains: %s " % ( values , " , " . join ( domains ) ) )
setattr ( namespace , self . dest , values )
else :
newval = getattr ( namespace , self . dest )
if not newval :
newval = [ ]
for v in values :
python: replace aliases with corresponding type names
Aliases are not used in the selinux database. When user enters a type
alias as a parameter it should be converted to the corresponding type
in order to be processed correctly further in the userspace logic.
Fixes e.g.:
\#sepolicy transition -s phpfpm_t
/* where phpfpm_t is a type alias of httpd_t */
Traceback (most recent call last):
File "/usr/bin/sepolicy", line 691, in <module>
args.func(args)
File "/usr/bin/sepolicy", line 458, in transition
mytrans = setrans(args.source, args.target)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 48, in __init__
self._process(self.source)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 54, in _process
trans = _get_trans(source)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 36, in _get_trans
src_list = [src] + list(filter(lambda x: x['name'] == src, sepolicy.get_all_types_info()))[0]['attributes']
IndexError: list index out of range
2018-10-30 15:26:29 +00:00
v = sepolicy . get_real_type_name ( v )
if v not in domains :
2013-01-11 19:23:09 +00:00
raise ValueError ( " %s must be an SELinux process domain: \n Valid domains: %s " % ( v , " , " . join ( domains ) ) )
newval . append ( v )
setattr ( namespace , self . dest , newval )
all_classes = None
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
class CheckClass ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
global all_classes
if not all_classes :
2015-07-24 08:07:13 +00:00
all_classes = map ( lambda x : x [ ' name ' ] , sepolicy . info ( sepolicy . TCLASS ) )
2013-01-11 19:23:09 +00:00
if values not in all_classes :
raise ValueError ( " %s must be an SELinux class: \n Valid classes: %s " % ( values , " , " . join ( all_classes ) ) )
setattr ( namespace , self . dest , values )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
class CheckAdmin ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
from sepolicy . interface import get_admin
newval = getattr ( namespace , self . dest )
if not newval :
newval = [ ]
admins = get_admin ( )
if values not in admins :
raise ValueError ( " %s must be an SELinux admin domain: \n Valid admin domains: %s " % ( values , " , " . join ( admins ) ) )
newval . append ( values )
setattr ( namespace , self . dest , newval )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
class CheckPort ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
newval = getattr ( namespace , self . dest )
if not newval :
newval = [ ]
for v in values :
if v < 1 or v > 65536 :
raise ValueError ( " %s must be an integer between 1 and 65536 " % v )
newval . append ( v )
setattr ( namespace , self . dest , newval )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
class CheckPortType ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
2013-10-11 14:16:57 +00:00
port_types = sepolicy . get_all_port_types ( )
2013-01-11 19:23:09 +00:00
newval = getattr ( namespace , self . dest )
if not newval :
newval = [ ]
for v in values :
python: replace aliases with corresponding type names
Aliases are not used in the selinux database. When user enters a type
alias as a parameter it should be converted to the corresponding type
in order to be processed correctly further in the userspace logic.
Fixes e.g.:
\#sepolicy transition -s phpfpm_t
/* where phpfpm_t is a type alias of httpd_t */
Traceback (most recent call last):
File "/usr/bin/sepolicy", line 691, in <module>
args.func(args)
File "/usr/bin/sepolicy", line 458, in transition
mytrans = setrans(args.source, args.target)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 48, in __init__
self._process(self.source)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 54, in _process
trans = _get_trans(source)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 36, in _get_trans
src_list = [src] + list(filter(lambda x: x['name'] == src, sepolicy.get_all_types_info()))[0]['attributes']
IndexError: list index out of range
2018-10-30 15:26:29 +00:00
v = sepolicy . get_real_type_name ( v )
if v not in port_types :
2013-01-11 19:23:09 +00:00
raise ValueError ( " %s must be an SELinux port type: \n Valid port types: %s " % ( v , " , " . join ( port_types ) ) )
newval . append ( v )
python: replace aliases with corresponding type names
Aliases are not used in the selinux database. When user enters a type
alias as a parameter it should be converted to the corresponding type
in order to be processed correctly further in the userspace logic.
Fixes e.g.:
\#sepolicy transition -s phpfpm_t
/* where phpfpm_t is a type alias of httpd_t */
Traceback (most recent call last):
File "/usr/bin/sepolicy", line 691, in <module>
args.func(args)
File "/usr/bin/sepolicy", line 458, in transition
mytrans = setrans(args.source, args.target)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 48, in __init__
self._process(self.source)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 54, in _process
trans = _get_trans(source)
File "/usr/lib/python3.6/site-packages/sepolicy/transition.py", line 36, in _get_trans
src_list = [src] + list(filter(lambda x: x['name'] == src, sepolicy.get_all_types_info()))[0]['attributes']
IndexError: list index out of range
2018-10-30 15:26:29 +00:00
setattr ( namespace , self . dest , newval )
2013-01-11 19:23:09 +00:00
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
class LoadPolicy ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
import sepolicy
sepolicy . policy ( values )
setattr ( namespace , self . dest , values )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
class CheckUser ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def __call__ ( self , parser , namespace , value , option_string = None ) :
newval = getattr ( namespace , self . dest )
if not newval :
newval = [ ]
2013-10-11 14:16:57 +00:00
users = sepolicy . get_all_users ( )
2013-01-11 19:23:09 +00:00
if value not in users :
2015-07-24 08:07:13 +00:00
raise ValueError ( " %s must be an SELinux user: \n Valid users: %s " % ( value , " , " . join ( users ) ) )
2013-01-11 19:23:09 +00:00
newval . append ( value )
setattr ( namespace , self . dest , newval )
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
class CheckRole ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
def __call__ ( self , parser , namespace , value , option_string = None ) :
newval = getattr ( namespace , self . dest )
if not newval :
newval = [ ]
roles = sepolicy . get_all_roles ( )
if value not in roles :
2015-07-24 08:07:13 +00:00
raise ValueError ( " %s must be an SELinux role: \n Valid roles: %s " % ( value , " , " . join ( roles ) ) )
2013-10-11 14:16:57 +00:00
newval . append ( value [ : - 2 ] )
setattr ( namespace , self . dest , newval )
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
class InterfaceInfo ( argparse . Action ) :
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
def __call__ ( self , parser , namespace , values , option_string = None ) :
2015-07-24 08:07:13 +00:00
from sepolicy . interface import get_interface_dict
2013-10-11 14:16:57 +00:00
interface_dict = get_interface_dict ( )
for v in values :
if v not in interface_dict . keys ( ) :
raise ValueError ( _ ( " Interface %s does not exist. " ) % v )
setattr ( namespace , self . dest , values )
2015-07-24 08:07:13 +00:00
def generate_custom_usage ( usage_text , usage_dict ) :
2013-10-11 14:16:57 +00:00
sorted_keys = [ ]
for i in usage_dict . keys ( ) :
sorted_keys . append ( i )
sorted_keys . sort ( )
for k in sorted_keys :
2015-07-24 08:07:13 +00:00
usage_text + = " %s %s | " % ( k , ( " " . join ( usage_dict [ k ] ) ) )
2013-10-11 14:16:57 +00:00
usage_text = usage_text [ : - 1 ] + " ] "
usage_text = _ ( usage_text )
return usage_text
2017-06-02 20:01:31 +00:00
# expects formats:
# "22 (sshd_t)", "80, 8080 (httpd_t)", "all ports (port_type)"
def port_string_to_num ( val ) :
2013-10-11 14:16:57 +00:00
try :
2017-06-02 20:01:31 +00:00
return int ( val . split ( " " ) [ 0 ] . split ( " , " ) [ 0 ] . split ( " - " ) [ 0 ] )
2013-10-11 14:16:57 +00:00
except :
2017-06-02 20:01:31 +00:00
return 99999999
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
2013-01-11 19:23:09 +00:00
def _print_net ( src , protocol , perm ) :
2013-10-11 14:16:57 +00:00
import sepolicy . network
portdict = sepolicy . network . get_network_connect ( src , protocol , perm )
2013-01-11 19:23:09 +00:00
if len ( portdict ) > 0 :
2015-07-24 08:07:13 +00:00
bold_start = " \033 [1m "
bold_end = " \033 [0;0m "
2016-11-07 09:51:08 +00:00
print ( " \n " + bold_start + " %s : %s %s " % ( src , protocol , perm ) + bold_end )
2015-07-24 08:07:13 +00:00
port_strings = [ ]
boolean_text = " "
2013-01-11 19:23:09 +00:00
for p in portdict :
2013-10-11 14:16:57 +00:00
for t , recs in portdict [ p ] :
2015-07-24 08:07:13 +00:00
cond = get_conditionals ( src , t , " %s _socket " % protocol , [ perm ] )
2013-10-11 14:16:57 +00:00
if cond :
2015-07-24 08:07:13 +00:00
boolean_text = get_conditionals_format_text ( cond )
2013-10-11 14:16:57 +00:00
port_strings . append ( " %s ( %s ) %s " % ( " , " . join ( recs ) , t , boolean_text ) )
else :
port_strings . append ( " %s ( %s ) " % ( " , " . join ( recs ) , t ) )
2017-06-02 20:01:31 +00:00
port_strings . sort ( key = lambda param : port_string_to_num ( param ) )
2013-10-11 14:16:57 +00:00
for p in port_strings :
2016-11-07 09:51:08 +00:00
print ( " \t " + p )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def network ( args ) :
2013-10-11 14:16:57 +00:00
portrecs , portrecsbynum = sepolicy . gen_port_dict ( )
all_ports = [ ]
2013-01-11 19:23:09 +00:00
if args . list_ports :
for i in portrecs :
if i [ 0 ] not in all_ports :
all_ports . append ( i [ 0 ] )
all_ports . sort ( )
2016-11-07 09:51:08 +00:00
print ( " \n " . join ( all_ports ) )
2013-01-11 19:23:09 +00:00
2013-10-11 14:16:57 +00:00
for port in args . port :
found = False
for i in portrecsbynum :
if i [ 0 ] < = port and port < = i [ 1 ] :
if i [ 0 ] == i [ 1 ] :
range = i [ 0 ]
2013-01-11 19:23:09 +00:00
else :
2013-10-11 14:16:57 +00:00
range = " %s - %s " % ( i [ 0 ] , i [ 1 ] )
found = True
2016-11-07 09:51:08 +00:00
print ( " %d : %s %s %s " % ( port , i [ 2 ] , portrecsbynum [ i ] [ 0 ] , range ) )
2013-10-11 14:16:57 +00:00
if not found :
if port < 500 :
2016-11-07 09:51:08 +00:00
print ( " Undefined reserved port type " )
2013-10-11 14:16:57 +00:00
else :
2016-11-07 09:51:08 +00:00
print ( " Undefined port type " )
2013-10-11 14:16:57 +00:00
for t in args . type :
2015-07-24 08:07:13 +00:00
if ( t , ' tcp ' ) in portrecs . keys ( ) :
2016-11-07 09:51:08 +00:00
print ( " %s : tcp: %s " % ( t , " , " . join ( portrecs [ t , ' tcp ' ] ) ) )
2015-07-24 08:07:13 +00:00
if ( t , ' udp ' ) in portrecs . keys ( ) :
2016-11-07 09:51:08 +00:00
print ( " %s : udp: %s " % ( t , " , " . join ( portrecs [ t , ' udp ' ] ) ) )
2013-10-11 14:16:57 +00:00
for a in args . applications :
d = sepolicy . get_init_transtype ( a )
if d :
args . domain . append ( d )
for d in args . domain :
_print_net ( d , " tcp " , " name_connect " )
for net in ( " tcp " , " udp " ) :
_print_net ( d , net , " name_bind " )
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
def gui_run ( args ) :
try :
import sepolicy . gui
sepolicy . gui . SELinuxGui ( args . domain , args . test )
pass
except ImportError :
raise ValueError ( _ ( " You need to install policycoreutils-gui package to use the gui option " ) )
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
def gen_gui_args ( parser ) :
gui = parser . add_parser ( " gui " ,
help = _ ( ' Graphical User Interface for SELinux Policy ' ) )
gui . add_argument ( " -d " , " --domain " , default = None ,
2015-07-24 08:07:13 +00:00
action = CheckDomain ,
help = _ ( " Domain name(s) of man pages to be created " ) )
2013-10-11 14:16:57 +00:00
gui . add_argument ( " -t " , " --test " , default = False , action = " store_true " ,
2015-07-24 08:07:13 +00:00
help = argparse . SUPPRESS )
2013-10-11 14:16:57 +00:00
gui . set_defaults ( func = gui_run )
2013-01-11 19:23:09 +00:00
2015-07-24 08:07:13 +00:00
2019-10-18 09:20:05 +00:00
def manpage_work ( domain , path , root , source_files , web ) :
from sepolicy . manpage import ManPage
m = ManPage ( domain , path , root , source_files , web )
print ( m . get_man_page_path ( ) )
2022-11-18 12:51:52 +00:00
return ( m . manpage_domains , m . manpage_roles )
2019-10-18 09:20:05 +00:00
2013-01-11 19:23:09 +00:00
def manpage ( args ) :
2022-11-18 12:51:52 +00:00
from sepolicy . manpage import HTMLManPages , gen_domains
2013-01-11 19:23:09 +00:00
path = args . path
2013-10-11 14:16:57 +00:00
if not args . policy and args . root != " / " :
sepolicy . policy ( sepolicy . get_installed_policy ( args . root ) )
if args . source_files and args . root == " / " :
raise ValueError ( _ ( " Alternative root needs to be setup " ) )
2013-01-11 19:23:09 +00:00
if args . all :
test_domains = gen_domains ( )
else :
test_domains = args . domain
2022-11-18 12:51:52 +00:00
manpage_domains = set ( )
manpage_roles = set ( )
2019-10-18 09:20:05 +00:00
p = Pool ( )
2022-11-18 12:51:52 +00:00
async_results = [ ]
2013-01-11 19:23:09 +00:00
for domain in test_domains :
2022-11-18 12:51:52 +00:00
async_results . append ( p . apply_async ( manpage_work , [ domain , path , args . root , args . source_files , args . web ] ) )
for result in async_results :
domains , roles = result . get ( )
manpage_domains . update ( domains )
manpage_roles . update ( roles )
2019-10-18 09:20:05 +00:00
p . close ( )
p . join ( )
2013-01-11 19:23:09 +00:00
if args . web :
HTMLManPages ( manpage_roles , manpage_domains , path , args . os )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def gen_manpage_args ( parser ) :
2013-10-11 14:16:57 +00:00
man = parser . add_parser ( " manpage " ,
help = _ ( ' Generate SELinux man pages ' ) )
man . add_argument ( " -p " , " --path " , dest = " path " , default = " /tmp " ,
help = _ ( " path in which the generated SELinux man pages will be stored " ) )
man . add_argument ( " -o " , " --os " , dest = " os " , default = get_os_version ( ) ,
help = _ ( " name of the OS for man pages " ) )
man . add_argument ( " -w " , " --web " , dest = " web " , default = False , action = " store_true " ,
help = _ ( " Generate HTML man pages structure for selected SELinux man page " ) )
man . add_argument ( " -r " , " --root " , dest = " root " , default = " / " ,
help = _ ( " Alternate root directory, defaults to / " ) )
man . add_argument ( " --source_files " , dest = " source_files " , default = False , action = " store_true " ,
help = _ ( " With this flag, alternative root path needs to include file context files and policy.xml file " ) )
group = man . add_mutually_exclusive_group ( required = True )
group . add_argument ( " -a " , " --all " , dest = " all " , default = False ,
action = " store_true " ,
help = _ ( " All domains " ) )
group . add_argument ( " -d " , " --domain " , nargs = " + " ,
action = CheckDomain ,
help = _ ( " Domain name(s) of man pages to be created " ) )
man . set_defaults ( func = manpage )
2013-01-11 19:23:09 +00:00
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def gen_network_args ( parser ) :
2015-07-24 08:07:13 +00:00
net = parser . add_parser ( " network " ,
help = _ ( ' Query SELinux policy network information ' ) )
group = net . add_mutually_exclusive_group ( required = True )
group . add_argument ( " -l " , " --list " , dest = " list_ports " ,
action = " store_true " ,
help = _ ( " list all SELinux port types " ) )
group . add_argument ( " -p " , " --port " , dest = " port " , default = [ ] ,
action = CheckPort , nargs = " + " , type = int ,
help = _ ( " show SELinux type related to the port " ) )
group . add_argument ( " -t " , " --type " , dest = " type " , default = [ ] ,
action = CheckPortType , nargs = " + " ,
help = _ ( " Show ports defined for this SELinux type " ) )
group . add_argument ( " -d " , " --domain " , dest = " domain " , default = [ ] ,
action = CheckDomain , nargs = " + " ,
help = _ ( " show ports to which this domain can bind and/or connect " ) )
group . add_argument ( " -a " , " --application " , dest = " applications " , default = [ ] ,
nargs = " + " ,
help = _ ( " show ports to which this application can bind and/or connect " ) )
net . set_defaults ( func = network )
2013-01-11 19:23:09 +00:00
def communicate ( args ) :
2015-07-24 08:07:13 +00:00
from sepolicy . communicate import get_types
2013-01-11 19:23:09 +00:00
2015-07-24 08:07:13 +00:00
writable = get_types ( args . source , args . tclass , args . sourceaccess . split ( " , " ) )
readable = get_types ( args . target , args . tclass , args . targetaccess . split ( " , " ) )
out = list ( set ( writable ) & set ( readable ) )
for t in out :
2016-11-07 09:51:08 +00:00
print ( t )
2013-01-11 19:23:09 +00:00
def gen_communicate_args ( parser ) :
comm = parser . add_parser ( " communicate " ,
help = _ ( ' query SELinux policy to see if domains can communicate with each other ' ) )
comm . add_argument ( " -s " , " --source " , dest = " source " ,
action = CheckDomain , required = True ,
help = _ ( " Source Domain " ) )
comm . add_argument ( " -t " , " --target " , dest = " target " ,
action = CheckDomain , required = True ,
help = _ ( " Target Domain " ) )
comm . add_argument ( " -c " , " --class " , required = False , dest = " tclass " ,
action = CheckClass ,
default = " file " , help = " class to use for communications, Default ' file ' " )
2015-07-24 08:07:13 +00:00
comm . add_argument ( " -S " , " --sourceaccess " , required = False , dest = " sourceaccess " , default = " open,write " , help = " comma separate list of permissions for the source type to use, Default ' open,write ' " )
comm . add_argument ( " -T " , " --targetaccess " , required = False , dest = " targetaccess " , default = " open,read " , help = " comma separated list of permissions for the target type to use, Default ' open,read ' " )
2013-01-11 19:23:09 +00:00
comm . set_defaults ( func = communicate )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def booleans ( args ) :
from sepolicy import boolean_desc
if args . all :
rc , args . booleans = selinux . security_get_boolean_names ( )
args . booleans . sort ( )
for b in args . booleans :
2016-11-07 09:51:08 +00:00
print ( " %s =_( \" %s \" ) " % ( b , boolean_desc ( b ) ) )
2013-01-11 19:23:09 +00:00
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def gen_booleans_args ( parser ) :
bools = parser . add_parser ( " booleans " ,
help = _ ( ' query SELinux Policy to see description of booleans ' ) )
group = bools . add_mutually_exclusive_group ( required = True )
group . add_argument ( " -a " , " --all " , dest = " all " , default = False ,
action = " store_true " ,
help = _ ( " get all booleans descriptions " ) )
group . add_argument ( " -b " , " --boolean " , dest = " booleans " , nargs = " + " ,
2013-10-11 14:16:57 +00:00
action = CheckBoolean , required = False ,
2013-01-11 19:23:09 +00:00
help = _ ( " boolean to get description " ) )
bools . set_defaults ( func = booleans )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def transition ( args ) :
from sepolicy . transition import setrans
mytrans = setrans ( args . source , args . target )
mytrans . output ( )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def gen_transition_args ( parser ) :
trans = parser . add_parser ( " transition " ,
help = _ ( ' query SELinux Policy to see how a source process domain can transition to the target process domain ' ) )
trans . add_argument ( " -s " , " --source " , dest = " source " ,
action = CheckDomain , required = True ,
help = _ ( " source process domain " ) )
trans . add_argument ( " -t " , " --target " , dest = " target " ,
action = CheckDomain ,
help = _ ( " target process domain " ) )
trans . set_defaults ( func = transition )
2015-07-24 08:07:13 +00:00
2013-10-11 14:16:57 +00:00
def print_interfaces ( interfaces , args , append = " " ) :
from sepolicy . interface import get_interface_format_text , interface_compile_test
for i in interfaces :
if args . verbose :
try :
2016-11-07 09:51:08 +00:00
print ( get_interface_format_text ( i + append ) )
2013-10-11 14:16:57 +00:00
except KeyError :
2016-11-07 09:51:08 +00:00
print ( i )
2013-10-11 14:16:57 +00:00
if args . compile :
try :
interface_compile_test ( i )
except KeyError :
2016-11-07 09:51:08 +00:00
print ( i )
2013-10-11 14:16:57 +00:00
else :
2016-11-07 09:51:08 +00:00
print ( i )
2013-10-11 14:16:57 +00:00
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def interface ( args ) :
2013-10-11 14:16:57 +00:00
from sepolicy . interface import get_admin , get_user , get_interface_dict , get_all_interfaces
2013-01-11 19:23:09 +00:00
if args . list_admin :
2013-10-11 14:16:57 +00:00
print_interfaces ( get_admin ( args . file ) , args , " _admin " )
2013-01-11 19:23:09 +00:00
if args . list_user :
2013-10-11 14:16:57 +00:00
print_interfaces ( get_user ( args . file ) , args , " _role " )
2013-01-11 19:23:09 +00:00
if args . list :
2013-10-11 14:16:57 +00:00
print_interfaces ( get_all_interfaces ( args . file ) , args )
if args . interfaces :
2015-07-24 08:07:13 +00:00
print_interfaces ( args . interfaces , args )
2013-01-11 19:23:09 +00:00
def generate ( args ) :
2013-10-11 14:16:57 +00:00
from sepolicy . generate import policy , AUSER , RUSER , EUSER , USERS , SANDBOX , APPLICATIONS , NEWTYPE
2013-01-11 19:23:09 +00:00
cmd = None
2013-10-11 14:16:57 +00:00
# numbers present POLTYPE defined in sepolicy.generate
2015-07-24 08:07:13 +00:00
conflict_args = { ' TYPES ' : ( NEWTYPE , ) , ' DOMAIN ' : ( EUSER , ) , ' ADMIN_DOMAIN ' : ( AUSER , RUSER , EUSER , ) }
2013-10-11 14:16:57 +00:00
error_text = " "
if args . policytype is None :
generate_usage = generate_custom_usage ( usage , usage_dict )
for k in usage_dict :
error_text + = " %s " % ( k )
print ( generate_usage )
print ( _ ( " sepolicy generate: error: one of the arguments %s is required " ) % error_text )
sys . exit ( 1 )
if args . policytype in APPLICATIONS :
2013-01-11 19:23:09 +00:00
if not args . command :
raise ValueError ( _ ( " Command required for this type of policy " ) )
cmd = os . path . realpath ( args . command )
if not args . name :
2015-07-24 08:07:13 +00:00
args . name = os . path . basename ( cmd ) . replace ( " - " , " _ " )
2013-01-11 19:23:09 +00:00
mypolicy = policy ( args . name , args . policytype )
if cmd :
mypolicy . set_program ( cmd )
if args . types :
2013-10-11 14:16:57 +00:00
if args . policytype not in conflict_args [ ' TYPES ' ] :
raise ValueError ( _ ( " -t option can not be used with ' %s ' domains. Read usage for more details. " ) % sepolicy . generate . poltype [ args . policytype ] )
2013-01-11 19:23:09 +00:00
mypolicy . set_types ( args . types )
2013-10-11 14:16:57 +00:00
if args . domain :
if args . policytype not in conflict_args [ ' DOMAIN ' ] :
raise ValueError ( _ ( " -d option can not be used with ' %s ' domains. Read usage for more details. " ) % sepolicy . generate . poltype [ args . policytype ] )
if args . admin_domain :
if args . policytype not in conflict_args [ ' ADMIN_DOMAIN ' ] :
raise ValueError ( _ ( " -a option can not be used with ' %s ' domains. Read usage for more details. " ) % sepolicy . generate . poltype [ args . policytype ] )
if len ( args . writepaths ) > 0 and args . policytype == NEWTYPE :
2015-07-24 08:07:13 +00:00
raise ValueError ( _ ( " -w option can not be used with the --newtype option " ) )
2013-10-11 14:16:57 +00:00
2013-01-11 19:23:09 +00:00
for p in args . writepaths :
if os . path . isdir ( p ) :
mypolicy . add_dir ( p )
else :
mypolicy . add_file ( p )
mypolicy . set_transition_users ( args . user )
2013-10-11 14:16:57 +00:00
mypolicy . set_admin_roles ( args . role )
2013-01-11 19:23:09 +00:00
mypolicy . set_admin_domains ( args . admin_domain )
mypolicy . set_existing_domains ( args . domain )
if args . policytype in APPLICATIONS :
mypolicy . gen_writeable ( )
mypolicy . gen_symbols ( )
2016-11-07 09:51:08 +00:00
print ( mypolicy . generate ( args . path ) )
2013-01-11 19:23:09 +00:00
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def gen_interface_args ( parser ) :
itf = parser . add_parser ( " interface " ,
help = _ ( ' List SELinux Policy interfaces ' ) )
2013-10-11 14:16:57 +00:00
itf . add_argument ( " -c " , " --compile " , dest = " compile " ,
action = " store_true " , default = False ,
help = " Run compile test for selected interface " )
itf . add_argument ( " -v " , " --verbose " , dest = " verbose " ,
action = " store_true " , default = False ,
help = " Show verbose information " )
itf . add_argument ( " -f " , " --file " , dest = " file " ,
help = " Interface file " )
2013-01-11 19:23:09 +00:00
group = itf . add_mutually_exclusive_group ( required = True )
2015-07-24 08:07:13 +00:00
group . add_argument ( " -a " , " --list_admin " , dest = " list_admin " , action = " store_true " , default = False ,
2013-10-11 14:16:57 +00:00
help = " List all domains with admin interface - DOMAIN_admin() " )
2015-07-24 08:07:13 +00:00
group . add_argument ( " -u " , " --list_user " , dest = " list_user " , action = " store_true " ,
2013-01-11 19:23:09 +00:00
default = False ,
2013-10-11 14:16:57 +00:00
help = " List all domains with SELinux user role interface - DOMAIN_role() " )
2015-07-24 08:07:13 +00:00
group . add_argument ( " -l " , " --list " , dest = " list " , action = " store_true " ,
2013-01-11 19:23:09 +00:00
default = False ,
help = " List all interfaces " )
2013-10-11 14:16:57 +00:00
group . add_argument ( " -i " , " --interfaces " , nargs = " + " , dest = " interfaces " ,
action = InterfaceInfo ,
help = _ ( " Enter interface names, you wish to query " ) )
2013-01-11 19:23:09 +00:00
itf . set_defaults ( func = interface )
2015-07-24 08:07:13 +00:00
2013-01-11 19:23:09 +00:00
def gen_generate_args ( parser ) :
2018-08-04 12:47:16 +00:00
from sepolicy . generate import get_poltype_desc , poltype , DAEMON , DBUS , INETD , CGI , SANDBOX , USER , EUSER , TUSER , XUSER , LUSER , AUSER , RUSER , NEWTYPE
2013-10-11 14:16:57 +00:00
generate_usage = generate_custom_usage ( usage , usage_dict )
2015-07-24 08:07:13 +00:00
pol = parser . add_parser ( " generate " , usage = generate_usage ,
2013-01-11 19:23:09 +00:00
help = _ ( ' Generate SELinux Policy module template ' ) )
pol . add_argument ( " -d " , " --domain " , dest = " domain " , default = [ ] ,
action = CheckDomain , nargs = " * " ,
help = _ ( " Enter domain type which you will be extending " ) )
pol . add_argument ( " -u " , " --user " , dest = " user " , default = [ ] ,
2015-07-24 08:07:13 +00:00
action = CheckUser ,
2013-01-11 19:23:09 +00:00
help = _ ( " Enter SELinux user(s) which will transition to this domain " ) )
2013-10-11 14:16:57 +00:00
pol . add_argument ( " -r " , " --role " , dest = " role " , default = [ ] ,
action = CheckRole ,
help = _ ( " Enter SELinux role(s) to which the administror domain will transition " ) )
2015-07-24 08:07:13 +00:00
pol . add_argument ( " -a " , " --admin " , dest = " admin_domain " , default = [ ] ,
2013-01-11 19:23:09 +00:00
action = CheckAdmin ,
2013-10-11 14:16:57 +00:00
help = _ ( " Enter domain(s) which this confined admin will administrate " ) )
2013-01-11 19:23:09 +00:00
pol . add_argument ( " -n " , " --name " , dest = " name " ,
default = None ,
help = _ ( " name of policy to generate " ) )
pol . add_argument ( " -T " , " --test " , dest = " test " , default = False , action = " store_true " ,
help = argparse . SUPPRESS )
pol . add_argument ( " -t " , " --type " , dest = " types " , default = [ ] , nargs = " * " ,
2015-07-24 08:07:13 +00:00
action = CheckType ,
2013-10-11 14:16:57 +00:00
help = " Enter type(s) for which you will generate new definition and rule(s) " )
2013-01-11 19:23:09 +00:00
pol . add_argument ( " -p " , " --path " , dest = " path " , default = os . getcwd ( ) ,
help = _ ( " path in which the generated policy files will be stored " ) )
2015-07-24 08:07:13 +00:00
pol . add_argument ( " -w " , " --writepath " , dest = " writepaths " , nargs = " * " , default = [ ] ,
2013-01-11 19:23:09 +00:00
help = _ ( " path to which the confined processes will need to write " ) )
2013-10-11 14:16:57 +00:00
cmdtype = pol . add_argument_group ( _ ( " Policy types which require a command " ) )
cmdgroup = cmdtype . add_mutually_exclusive_group ( required = False )
cmdgroup . add_argument ( " --application " , dest = " policytype " , const = USER ,
2015-07-24 08:07:13 +00:00
action = " store_const " ,
help = _ ( " Generate ' %s ' policy " ) % poltype [ USER ] )
2013-10-11 14:16:57 +00:00
cmdgroup . add_argument ( " --cgi " , dest = " policytype " , const = CGI ,
2015-07-24 08:07:13 +00:00
action = " store_const " ,
help = _ ( " Generate ' %s ' policy " ) % poltype [ CGI ] )
2013-10-11 14:16:57 +00:00
cmdgroup . add_argument ( " --dbus " , dest = " policytype " , const = DBUS ,
2015-07-24 08:07:13 +00:00
action = " store_const " ,
help = _ ( " Generate ' %s ' policy " ) % poltype [ DBUS ] )
2013-10-11 14:16:57 +00:00
cmdgroup . add_argument ( " --inetd " , dest = " policytype " , const = INETD ,
2015-07-24 08:07:13 +00:00
action = " store_const " ,
help = _ ( " Generate ' %s ' policy " ) % poltype [ INETD ] )
2013-10-11 14:16:57 +00:00
cmdgroup . add_argument ( " --init " , dest = " policytype " , const = DAEMON ,
2015-07-24 08:07:13 +00:00
action = " store_const " , default = DAEMON ,
help = _ ( " Generate ' %s ' policy " ) % poltype [ DAEMON ] )
2013-10-11 14:16:57 +00:00
type = pol . add_argument_group ( " Policy types which do not require a command " )
group = type . add_mutually_exclusive_group ( required = False )
group . add_argument ( " --admin_user " , dest = " policytype " , const = AUSER ,
2013-01-11 19:23:09 +00:00
action = " store_const " ,
2013-10-11 14:16:57 +00:00
help = _ ( " Generate ' %s ' policy " ) % poltype [ AUSER ] )
2013-01-11 19:23:09 +00:00
group . add_argument ( " --confined_admin " , dest = " policytype " , const = RUSER ,
action = " store_const " ,
2013-10-11 14:16:57 +00:00
help = _ ( " Generate ' %s ' policy " ) % poltype [ RUSER ] )
2013-01-11 19:23:09 +00:00
group . add_argument ( " --customize " , dest = " policytype " , const = EUSER ,
action = " store_const " ,
2013-10-11 14:16:57 +00:00
help = _ ( " Generate ' %s ' policy " ) % poltype [ EUSER ] )
2013-01-11 19:23:09 +00:00
group . add_argument ( " --desktop_user " , dest = " policytype " , const = LUSER ,
action = " store_const " ,
2013-10-11 14:16:57 +00:00
help = _ ( " Generate ' %s ' policy " ) % poltype [ LUSER ] )
group . add_argument ( " --newtype " , dest = " policytype " , const = NEWTYPE ,
2013-01-11 19:23:09 +00:00
action = " store_const " ,
2013-10-11 14:16:57 +00:00
help = _ ( " Generate ' %s ' policy " ) % poltype [ NEWTYPE ] )
2013-01-11 19:23:09 +00:00
group . add_argument ( " --sandbox " , dest = " policytype " , const = SANDBOX ,
action = " store_const " ,
2013-10-11 14:16:57 +00:00
help = _ ( " Generate ' %s ' policy " ) % poltype [ SANDBOX ] )
2013-01-11 19:23:09 +00:00
group . add_argument ( " --term_user " , dest = " policytype " , const = TUSER ,
action = " store_const " ,
2013-10-11 14:16:57 +00:00
help = _ ( " Generate ' %s ' policy " ) % poltype [ TUSER ] )
2013-01-11 19:23:09 +00:00
group . add_argument ( " --x_user " , dest = " policytype " , const = XUSER ,
action = " store_const " ,
2013-10-11 14:16:57 +00:00
help = _ ( " Generate ' %s ' policy " ) % poltype [ XUSER ] )
2015-07-24 08:07:13 +00:00
pol . add_argument ( " command " , nargs = " ? " , default = None ,
2013-10-11 14:16:57 +00:00
help = _ ( " executable to confine " ) )
2013-01-11 19:23:09 +00:00
pol . set_defaults ( func = generate )
if __name__ == ' __main__ ' :
parser = argparse . ArgumentParser ( description = ' SELinux Policy Inspection Tool ' )
subparsers = parser . add_subparsers ( help = _ ( " commands " ) )
parser . add_argument ( " -P " , " --policy " , dest = " policy " ,
action = LoadPolicy ,
default = None , help = _ ( " Alternate SELinux policy, defaults to /sys/fs/selinux/policy " ) )
gen_booleans_args ( subparsers )
gen_communicate_args ( subparsers )
gen_generate_args ( subparsers )
2013-10-11 14:16:57 +00:00
gen_gui_args ( subparsers )
2013-01-11 19:23:09 +00:00
gen_interface_args ( subparsers )
gen_manpage_args ( subparsers )
gen_network_args ( subparsers )
gen_transition_args ( subparsers )
try :
2013-10-11 14:16:57 +00:00
if os . path . basename ( sys . argv [ 0 ] ) == " sepolgen " :
2015-11-16 21:10:43 +00:00
parser_args = [ " generate " ] + sys . argv [ 1 : ]
elif len ( sys . argv ) > 1 :
parser_args = sys . argv [ 1 : ]
2013-10-11 14:16:57 +00:00
else :
2015-11-16 21:10:43 +00:00
parser_args = [ " -h " ]
args = parser . parse_args ( args = parser_args )
2013-01-11 19:23:09 +00:00
args . func ( args )
sys . exit ( 0 )
2016-11-07 09:51:08 +00:00
except ValueError as e :
2013-01-11 19:23:09 +00:00
sys . stderr . write ( " %s : %s \n " % ( e . __class__ . __name__ , str ( e ) ) )
sys . exit ( 1 )
2016-11-07 09:51:08 +00:00
except IOError as e :
2013-10-11 14:16:57 +00:00
sys . stderr . write ( " %s : %s \n " % ( e . __class__ . __name__ , str ( e ) ) )
sys . exit ( 1 )
2013-01-11 19:23:09 +00:00
except KeyboardInterrupt :
2016-11-07 09:51:08 +00:00
print ( " Out " )
2013-01-11 19:23:09 +00:00
sys . exit ( 0 )