The rsbac package is a full interface to the RSBAC Linux security system, including support to manage the various models it provides. Its goal is to be easy to use, high-level, "object-oriented", complete and with acceptable performance. It allows to easily administrate the RSBAC configuration with the power of Python.
You can download a frequently updated release here.
A git repository is also available at git://git.tuxee.net/py-rsbac and a web interface to explore the repository is here.
Multithreading is not supported at all. Please use some lock to access the package in a multithread environment.
It was developped first for RSBAC 1.2.8 then for RSBAC 1.3.0, tested mainly on a x86 machine and a PowerPC (G4) machine.
The first release of this package will target full coverage of the RSBAC API (except for PM and MAC models which remain to be added.) More high-level tools built on top of it are planned (such as a GUI, new command line tools, a dedicated shell, backup tools or automatic deployment for example.)
The rsbac package provides some generic functions.
moduleVersion
The RSBAC Python package version as a tuple (major,middle,minor,extra) where extra is a string, and other components are integers.
kernelVersion
The RSBAC kernel version as a tuple (major,middle,minor).
libraryVersion
The RSBAC library version as a tuple (major,middle,minor).
headerVersion
The RSBAC headers version as a tuple (major,middle,minor).
dumpStats()
Dump statistics about RSBAC to kernel log.
checkConsistency(correct, checkInode)
Check RSBAC configuration consistency. The correct argument is 0 to do only a check, 1 to correct errors and 2 to correct even more errors. The checkInode argument is a boolean which indicate if inode numbers must also be checked or not.
writeDirtyList()
Write all dirty lists to disk. Returns number of lists written.
init(path)
Initialize a filesystem with RSBAC. This is normally not needed, since filesystems are automatically initialized on mount.
The librsbac.so provides various functions to retrieve symbolic names for most of the RSBAC constants and conversely to retrieve constant from the symbolic name. These various functions are provided in the rsbac python package.
For each types of constants, there are 3 functions defined as follow:
getFooNumber(name)
Retrieve the integer constant from the symbolic name name.
getFooName(n)
Retrieve the symbolic name from the integer constant n.
getFooNames()
Retrieve the list of names. Note that getFooNames()[n] is equivalent to getFooName(n), as long as n is valid.
There are the following functions:
getRequestName(n), getRequestNames(), getRequestNumber(name)
Name of the requests (ADD_TO_KERNEL, ALTER, APPEND_OPEN,..)
getResultName(n), getResultNames(), getResultNumber(name)
Name of the results (NOT_GRANTED, GRANTED,..)
getAttributeName(n), getAttributeNames(), getAttributeNumber(name)
Name of the attributes (pseudo, security_level, rc_type_fd,..)
getScdTypeName(n), getScdTypeNames(), getScdTypeNumber(name)
Name of the system control data (time_strucs, clock, host_id,..)
getTargetName(n), getTargetNames(), getTargetNumbel(name)
Name of the RSBAC target (FILE, DIR, NETTEMP_NT,..)
getIpcTargetName(n), getIpcTargetNames(), getIpcTargetNumber(name)
Name of the IPC types (sem, msg, shm,..)
getSwitchTargetName(n), getSwitchTargetNames(), getSwitchTargetNumber(name)
Name of the RSBAC modules (GEN, MAC, PM,..)
getCapName(n), getCapNames(), getCapNumber(name)
Name of the Linux capabilities (CHOWN, DAC_OVERRIDE, NET_RAW,..)
getRcTargetName(n), getRcTargetNames(), getRcTargetNumber(name)
Name of the RC target (ROLE and TYPE)
getRcAdminName(n), getRcAdminNames(), getRcAdminNumber(name)
Name of the RC admin types (no_admin, role_admin,..)
getRcScdTypeName(n), getRcScdTypeNames(), getRcScdTypeNumber(name)
Like ScdType, but with additionnal constants specific to the RC model.
getRcSpecialRightName(n), getRcSpecialRightNames(), getRcSpecialRightNumber(name)
Like Request, but with additionnal constants specific to the RC model.
getRessourceName(n), getRessourceNames(), getRessourceNumbers(name)
Name of the ressource (those settable by ulimit.) (cpu, stack, core,..)
getLogLevelName(n), getLogLevelNames(), getLogLevelNumber(name)
Name of the log levels (none, denied, full,..)
getAttributeModule(attribute)
Get the module ID to which an attribute belong. The attribute parameter is an integer.
getErrorName(n)
Get the name of the error identified by n. This value must be negative, and is usually below or equal to -1001. Be careful: All unknown errors are reported as "Success"!
getAttributeParameters(attribute)
Return a textual description of the attribute. The resulting string is only useful for debugging purpose.
getRcItemParameters(value)
Return a textual description of the RC item. The resulting string is only useful for debugging purpose.
openLog()
Open RSBAC log. Note: This function does nothing.
closeLog()
Close RSBAC log. Note: This function does nothing.
readLog(size=4096)
Read RSBAC log. Up to size bytes are read. Return a string.
readRingBuffer(size=4096)
Read the RSBAC ring buffer. Up to size bytes are read. Return a string.
readAndClearRingBuffer(size=4096)
Read then clear the RSBAC ring buffer. Up to size bytes are read. Return a string.
clearRingBuffer()
Clear the RSBAC ring buffer.
Each users have several type of roles for each of the RSBAC modules. For example, root default system role for the FF module is "administrator", while default system role for the security officer for this module is "security_officer" and all others users have the role "user". This way, each users can administrate or obtains rights for a given module.
The module rsbac.roles allows to represent the system roles (not related to RC roles!) The class SystemRole is already instantiated for the predefined RSBAC system role, which are:
roles.user
roles.security_officer
roles.administrator
roles.auditor
Since SystemRole class build singleton instances, it is possible to compare them with the is operator.
Several data types in RSBAC are in fact integers used as bit vector. For example, the rsbac_request_vector_t is an integer that hold a set of flags related to allowed requests. To manipulate them conveniently under Python, a class was created for each such types. So, for the rsbac_request_vector_t there is the corresponding rsbac.RequestVector data type in the rsbac package, and so on for other types.
Such classes provides an immutable set. To modify them, it is necessary to create a new instance. It is similar to string manipulations under Python, where a new string must be created for each operation.
The flags classes defined in the rsbac module are the following:
RequestVector, RcRequestVector, AclRequestVector
ScdVector, JailScdVector
FileFlags
PaxFlags
CapsFlags
JailFlags
Generic description follows: (where Flags name is for illustration purpose)
class Flags(init)
init is a versatile mean to specify an initial value. It can be either:
a string, naming a flag,
a tuple or a list, which is recursively visited and whose items are combined (OR'ed),
an integer or any object castable to an integer, representing a bit vector (each bit of the integer correspond to a flag.)
__iter__()
Return an iterator over each set flags. First the flags whose name is know are returned, then follows each integer representing unknown flag (each integer is a power of 2, to match the constructor requirement.)
__repr__()
Return a string representation of the instance such that executing the string give back the same object.
__int__()
__long__()
Return respectively an int or a long which is the integer with the bit pattern described by all the flags.
__cmp__(other)
Compare two instances. The order is stable but undefined.
__or__(other)
__xor__(other)
__and__(other)
Combine two instances with one of the respective boolean operator OR, XOR or AND. The other value should be either a Flags instance or a value accepted by the Flags constructor.
__invert__()
Return a new instance where all known flags are inverted. Unknown bit are kept unchanged.
FIXME: Give a better set of examples..
>>> import rsbac >>> rsbac.RequestVector() RequestVector() >>> rsbac.RequestVector('lock', 'connect', 'alter') RequestVector('alter', 'connect', 'lock') >>> int( rsbac.RequestVector('lock') ) 562949953421312L # 2**49 >>> rsbac.RequestVector( 2**49 ) RequestVector('lock') >>> int( rsbac.RequestVector('alter') ) 2 >>> rsbac.RequestVector( [ ( 'lock' , 'ioctl' ) , [ 'mount' ] , 2 ] ) RequestVector('alter', 'mount', 'ioctl', 'lock') >>> ~rsbac.RequestVector() RequestVector('add_to_kernel', 'alter', 'append_open', ..., 'ioctl', 'lock', 'authenticate') >>> rsbac.RequestVector('bind', 'listen') ^ rsbac.RequestVector('bind', 'connect') RequestVector('listen', 'connect') >>> rsbac.RequestVector('bind', 'listen') & ~rsbac.RequestVector('bind', 'connect') RequestVector('listen') >>> list( rsbac.RequestVector( 127 ) ) ['add_to_kernel', 'alter', 'append_open', 'change_group', 'change_owner', 'chdir', 'clone']
>>> a = rsbac.RequestVector( 'bind' ) >>> a |= 'listen' , 'connect' >>> a RequestVector('bind', 'listen', 'connect') >>> a &= ~rsbac.RequestVector( 'bind' , 'listen' ) >>> a RequestVector('connect')
At some places, some variables have a dict-like or a set-like interface, meaning that they can be used and updated like the usual Python dictionnaries or Python sets. These variables are usually dynamic, meaning that there contents reflect the state of the RSBAC configuration. Homever, such dictionnaries doesn't support standard method such as .copy or .fromkeys, because it makes no sense.
There is also a type named "TTL dict-like variable" at some place in this document. It's in fact a type sharing both set and dict interface. This type act as a dictionnary, where the values have the meaning described in the "TTL" section. To summarize: a value with False mean that there is no entry for the given key, True and positive integers mean that the entry exists, where an integer specify the TTL and True mean that the TTL is illimited.
The way to specify TTL in the rsbac package is a bit different from the usage in other RSBAC tools.
In other RSBAC tools (as understood internally in the kernel), a special value (maximum representable TTL value) is used when we want to preserve the TTL, 0 is for unlimited TTL and any other integers are interpreted as a duration in seconds.
But we have chosen another approach. In the rsbac package, None mean that we want to keep the TTL (thus we specify "no" TTL), False mean that the object doesn't exists (the TTL expired, or is undefined or unknown), True means unlimited TTL and any integer means a duration in seconds. Since TTL cannot be lower than 1s, any integers is clamped to this minimal duration. It means that 0 is also interpreted as a number of second, which is clamped to 1s. The whole point is to have a coherent behavior. (A better behavior could have been reached if it was possible to set the TTL to 0s to discard immediatly the corresponding settings in the RSBAC configuration.)
To summarize:
TTL | Meaning |
False | Expired TTL (No entry/no such object) |
integer | remaining TTL in seconds |
True | unlimited TTL |
None | ask to keep the current TTL |
RSBAC is divided into various models (aka modules, depending of the context.) There are for example the ACL, RC and PM modules. Each of these modules can be turned on and off (depending of kernel options when the kernel was compiled, or depending of the nature of the model), and their softmode may be enabled or disabled. Also, naturally, a model can be available or not, according to choice made when compiling the kernel.
The rsbac.module module provides a list of all the RSBAC modules known to the rsbac package. This module contains an instance of a module.Module class for each of them. There is also a module.all variable which is a list of all these instances.
Each module is represented by the following class:
class Module(..)
This class is not meant to be instantiated by the user.
__int__()
__long__()
Cast the module instance to the corresponding RSBAC identifier.
id
This read-only property is the RSBAC identifier for the module.
name
This read-only property is the name of the module.
available
This read-only property is a boolean, which is true if the module was compiled in the kernel and False otherwise. If the module is not available, then access to other properties will fail.
enabled
This read/write property is the state of the module. If true, the module is enabled. Otherwise, it is disabled.
switchableOn
This read-only property indicate if the module can be switched on.
switchableOff
This read-only property indicate if the module can be switched off.
softmode
This read/write property is the state of the softmode for the module. If true, the softmode is enabled. Otherwise, it is disabled.
softmodeSwitchableOn
This read-only property indicate if the softmode of the module can be switched on.
softmodeSwitchableOff
This read-only property indicate if the softmode of the module can be switched off.
RSBAC transactions are fully supported. To make them easy to use, it was chosen to use a global variable used internally by the rsbac package, rather than letting the user specify the current transaction manually when reading/modifying RSBAC system configuration. The module rsbac.transaction contains the class and functions needed to manage transaction.
The standard method to run a block of code with a new transaction and ensuring the transaction is correctly terminated even if exception occurs, is to use the transaction.withTransaction function.
withTransaction(function, uid=.., password=None, ttl=True)
Create a new transaction, then call function to which a Transaction instance is passed as the only argument. Anything happening while function is called, is performed with the corresponding transaction. The function must commit or forget the transaction at some point before returning. If the function doesn't terminate the transaction, then it is automatically canceled when the function returns. See the documentation of the Transaction instance below.
function is a callable taking one argument.
uid is the UID to which the transaction belong. The default value allows any users to use the transaction, in which case a password may be useful.
password is an optional password to protect the transaction. The default value doesn't define any password.
ttl, used to select the time to live of the transaction. The TTL cannot exceed the maximum duration specified in the kernel. The default is the maximum allowed TTL.
The transaction is represented by a instance of the following class:
class Transaction(..)
This class is not meant to be instantied by the user. See withTransaction to create and use such instance.
Its purpose is to represent an existing transaction, not to create them.
refresh(ttl=True)
Reset the TTL of the transaction. Default value is to extend the TTL to the maximum allowed duration.
commit()
Commit the transaction.
forget()
Forget (revert, cancel) the transaction.
def doSomething( transaction ) : doThing1() doThing2() if not doThing3() : transaction.forget() else : doThing4() transaction.commit() withTransaction( doSomething , ttl = 300 )
A central concept to RSBAC is the various Unix objects such as file system objects (file, directory, fifo pipe, ..), processes, network device and so on. To represent them, the rsbac.objects package provides a hierarchy of classes for each RSBAC object type. Through these classes, all RSBAC objects attributes can be read and written.
The module described below also contains 3 functions listAllDevices(), listAllUsers() and listAllGroups() which return the corresponding list of objects known to RSBAC.
Most of the following class contains a rcTypes attribute with a dict-like interface which gives access to all the defined RC type specific to the corresponding class. For more information, see the section discussing this topic.
All common filesystem objects are represented with one of the following class:
class FD(id)
class Directory(id)
class File(id)
class Symlink(id)
class Device(id)
class Fifo(id)
class UnixSocket(id)
The constructor takes a path to the file system objects.
The FD class is an abstract data type which resolve to the correct type (File, Directory, Symlink, Device, Fifo or UnixSocket) inside the RSBAC system (not by the rsbac Python package.)
__str__()
Return the ID (the path).
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.)
Class attribute:
rcTypes
A dict-like attribute which contains all FD RC types.
Additionnaly, there are some predefined instances to match particular RSBAC objects:
defaultFD
defaultFile
defaultFifo
defaultSymlink
defaultDirectory
defaultDevice
defaultUnixSocket
These instances are useful for the ACL entries on the default targets.
The following classes derive from the DeviceBase class.
It is different from the Device class which is instantiated with a path, while here we need the major and minor numbers.
class BlockDevice(major[, minor])
class CharacterDevice(major[, minor])
If minor is not specified, then construct an object that match any device with the specified major number.
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.)
Class attribute:
rcTypes
A dict-like attribute which contains all network device RC types.
See also um.User and um.Group for the UM specific settings related to users and groups.
The rsbac.um class contains the dict-like variable users and groups which gives access to all defined users and groups in RSBAC. Note that you should not perform a call like users.clear() (which remove ALL the users from the UM module) by mistake, especially if the system is configured to rely on RSBAC for all authentication.
addUser(name, uid=None, password=None, ttl=True)
Add an user to the UM module named 'name'. If uid is None, then an UID is automatically chosen, otherwise the argument specify the UID to use. The password if not None, specify the user password.
Return an User instance for the newly created account.
addGroup(name, gid=None, password=None, ttl=True)
Add an group to the UM module named 'name'. If uid is None, then an GID is automatically chosen, otherwise the argument specify the GID to use. The password if not None, specify the group password.
Return a Group instance for the newly created group.
class User(uid)
The uid is the UID of an Unix user.
removeFromAcl()
Remove all ACL entries on all objects whose subject is this user.
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.)
Class attribute:
rcTypes
A dict-like attribute which contains all user RC types.
There is also a module objects.pseudoUsers which contains predefined User instance to represent pseudo users named all_users and no_user.
class Group(gid)
The gid in the GID of an Unix group.
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.)
Class attribute:
rcTypes
A dict-like attribute which contains all group RC types.
There is also a module objects.pseudoGroups which contains predefined Group instance to represent pseudo groups named all_groups and no_group.
class Process(pid)
The pid is the PID of an Unix process.
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.) Note that it make sense only on the defaultProcess instance.
Class attribute:
rcTypes
A dict-like attribute which contains all process RC types.
There is also a defaultProcess instance to represent the default process (useful for the ACL entries.)
The following classes derive from the objects.Ipc class.
class IpcSem(semid)
A class to represent an IPC Semaphore with ID semid.
class IpcMsg(msgid)
A class to represent an IPC Message with ID msgid.
class IpcShm(shmid)
A class to represent an IPC Shared Memory with ID shmid.
class IpcAnonPipe(inode)
A class to represent an Anonymous pipe with inode inode (as created by pipe(2).)
class IpcMqueue(mqdes)
A class to represent a POSIX message queues with descriptor mqdes (as created by mq_open(3).)
Note that it doesn't appear to be supported by RSBAC however!
class IpcAnonUnix(inode)
A class to represent an Anonymous Unix socket with inode inode (as created by socketpair(2))
Class attribute:
rcTypes
A dict-like attribute which contains all IPC RC types.
class SCD(..)
The class SCD is not meant to be instantiated by the user. It is already instantiated for all known system objects (System Control Data) and these instances are availables in the module rsbac.objects.system (see below.)
rc_type
The RC type corresponding to the SCD object.
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.)
Class attribute:
rcTypes
A dict-like attribute which contains all SCD RC types.
There is also a defaultScd instance to represent the default SCD object.
>>> dir(rsbac.objects.system) ['__doc__', '__name__', 'capability', 'clock', 'firewall', 'host_id', 'ioports', 'kexec', 'kmem', 'ksyms', 'mlock', 'net_id', 'network', 'nfsd', 'none', 'other', 'priority', 'quota', 'rlimit', 'rsbac', 'rsbac_log', 'rsbac_remote_log', 'swap', 'sysctl', 'sysfs', 'syslog', 'time_strucs']
class NetworkDevice(name)
The name is the network device name.
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.)
Class attribute:
rcTypes
A dict-like attribute which contains all network device RC types.
There is also a defaultNetworkDevice instance to represent the default network device.
class NetworkTemplate(id)
The id is the ID of the RSBAC network template.
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.)
selfAcl
This dict-like attribute gives access to ACL entries for the template itself (not to the object matched by the template.) It's indexed by a subject (user, RC role or ACL group.)
FIXME: Choose another name for this attribute?
This class also contains specific attributes:
name
This read/write property is the name of the network template. Setting the name of an undefined network template creates it.
addresses
This read/write property is a tuple (address_family, addresses) where address_family is an integer as defined by the constants in the standard module socket (such as socket.AF_INET and so on) and addresses is a list of addresses (as string) specific to the address family. To represent the IPv4 address 127.0.0.1 and the IPv4 network 192.168.1.0/24, this property can be set to (socket.AF_INET, ['127.0.0.1', '192.168.1.0/24']).
socketType
This read/write property is the type of socket to match by the network template, as defined by the constants in the standard module socket (such as socket.SOCK_STREAM, socket.SOCK_DGRAM and so on). A value of 0 means any socket types.
protocol
This read/write property is the protocol to match by the network template, as defined by the constants in the standard module socket (such as socket.IPPROTO_TCP, socket.IPPROTO_UDP and so on). A value of 0 means any protocols.
networkDevice
This read/write property is the name of a network device. If empty, any network devices is matched.
ports
This read/write property is a list of range of ports. A range of a single port can be written as a single integer. To represent the ports 1024 to 1099, plus the single port 1200, the property is [(1024,1099), 1200].
Methods for this class are:
checkId()
Retrieve the ID of the network template if it is defined or throw an exception of type errors.Error if not found.
copyTo(target)
Copy the network template to a new one with ID target. The target network template can be an existing one.
delete()
Remove the network template from the RSBAC system.
A class method is provided to create new network templates:
create(id, name)
Create a new network template of ID id named with the string name. Return a NetworkTemplate instance for the newly created network template.
Class attribute:
rcTypes
A dict-like attribute which contains all network template RC types.
The module also provides a variable networkTemplates with a dict-like interface to give access to all defined network templates. A network template can be created with networkTemplates[id]=name, since setting the name of an undefined network template automatically creates it.
class NetworkObject(..)
This type is particular because it cannot really be instantiated from the userland. The reason is that it refers to a structure which is inside the kernel. See objects.defaultNetworkObject for the only instance available.
acl, eff_acl
This dict-like attribute gives access to ACL entries for the object. It's indexed by a subject (user, RC role or ACL group.)
There is however an instance objects.defaultNetworkObject to represent the default network object.
Class attribute:
rcTypes
A dict-like attribute which contains all network device RC types.
The following properties are part of the classes described is the previous section.
All the classes used to represent a RSBAC object give access to the set of RSBAC attributes for the corresponding object via properties. Each of these properties is of a type specific to the RSBAC attribute. The following table gives the name of the attributes, the module concerned (for information purpose, but not needed otherwise), the targets that own the attribute and the type as handled by the rsbac package.
For example, to retrieve the RC type of the process of PID 1 you can use rsbac.objects.Process(1).rc_type.
FIXME: Complete the following table.
Module | Attribute | Type | Target |
GEN | audit_uid | objects.User | Process |
GEN | auid_exempt | objects.User | FD, Process |
AUTH | auth_last_auth | objects.User | Process |
AUTH | auth_learn | bool | FD, Process |
AUTH | auth_may_set_cap | bool | FD, Process |
AUTH | auth_may_setuid | int | FD, Process |
AUTH | auth_role | SystemRole | User |
CAP | cap_ld_env | int | FD, Process, User |
CAP | cap_process_hiding | int | Process |
CAP | cap_role | SystemRole | User |
MAC | current_sec_level | Process | |
DAZ | daz_role | User | |
DAZ | daz_scanned | FD | |
DAZ | daz_scanner | FD, Process | |
GEN | fake_root_uid | int | FD, Process |
FF | ff_flags | FileFlags | FD |
FF | ff_role | SystemRole | User |
MAC | initial_security_level | Process, User | |
JAIL | jail_flags | JailFlags | Process |
JAIL | jail_id | int | Ipc, Process |
JAIL | jail_ip | IP² | Process |
JAIL | jail_max_caps | CapsFlags | Process |
JAIL | jail_parent | int | Process |
JAIL | jail_role | SystemRole | User |
JAIL | jail_scd_get | JailScdVector | Process |
JAIL | jail_scd_modify | JailScdVector | Process |
GEN | linux_dac_disable | int | FD |
GEN | local_log_array | - | NetworkObject |
MAC | local_mac_categories | - | NetworkObject |
PM | local_pm_ipc_purpose | - | NetworkObject |
PM | local_pm_object_class | - | NetworkObject |
PM | local_pm_object_type | - | NetworkObject |
RC | local_rc_type | - | NetworkObject |
MAC | local_sec_level | - | NetworkObject |
GEN | log_array | tuple³ | Device, FD, NetworkDevice, NetworkTemplate |
GEN | log_program_based | RequestVector | FD, Process |
GEN | log_user_based | RequestVector | User |
MAC | mac_auto | FD, Process | |
MAC | mac_categories | Device, FD, Ipc, NetworkTemplate, Process, User | |
MAC | mac_check | Device | |
MAC | mac_curr_categories | Process | |
MAC | mac_file_flags | FD | |
MAC | mac_initial_categories | Process, User | |
MAC | mac_min_categories | Process, User | |
MAC | mac_process_flags | Process | |
MAC | mac_prop_trusted | FD | |
MAC | mac_role | User | |
MAC | mac_user_flags | User | |
CAP | max_caps | CapsFlags | FD, User |
CAP | max_caps_program | Process | |
CAP | max_caps_user | Process | |
MAC | max_read_categories | Process | |
MAC | max_read_open | Process | |
CAP | min_caps | CapsFlags | FD, User |
MAC | min_security_level | Process, User | |
MAC | min_write_categories | Process | |
MAC | min_write_open | Process | |
PAX | pax_flags | PaxFlags | FD, Process |
PAX | pax_role | SystemRole | User |
PM | pm_current_task | Process | |
PM | pm_ipc_purpose | Ipc, NetworkTemplate | |
PM | pm_object_class | Device, FD, Ipc, NetworkTemplate | |
PM | pm_object_type | Device, FD, Ipc, NetworkTemplate | |
PM | pm_process_type | Process | |
PM | pm_role | User | |
PM | pm_task_set | User | |
PM | pm_tp | FD, Process | |
GEN | pseudo | - | User |
RC | rc_def_role | rc.Role | User |
RC | rc_force_role | rc.Role | FD, Process |
RC | rc_initial_role | rc.Role | FD |
RC | rc_role | rc.Role | Process |
RC | rc_select_type | rc.Type | Process |
RC | rc_type | rc.Type | Device, Group, Ipc, NetworkDevice, NetworkTemplate, Process, User |
RC | rc_type_fd | rc.Type | FD |
RC | rc_type_nt | rc.Type | NetworkTemplate |
GEN | remote_ip | IP² | Process |
GEN | remote_log_array | - | NetworkObject |
MAC | remote_mac_categories | - | NetworkObject |
PM | remote_pm_ipc_purpose | - | NetworkObject |
PM | remote_pm_object_class | - | NetworkObject |
PM | remote_pm_object_type | - | NetworkObject |
RC | remote_rc_type | - | NetworkObject |
MAC | remote_sec_level | - | NetworkObject |
RES | res_max | tuple³ | FD, User |
RES | res_min | tuple³ | FD, User |
RES | res_role | SystemRole | User |
MAC | security_level | Device, FD, Ipc, NetworkTemplate, Process, User | |
GEN | symlink_add_mac_level | bool | FD |
GEN | symlink_add_rc_role | bool | FD |
GEN | symlink_add_remote_ip | bool | FD |
GEN | symlink_add_uid | bool | FD |
Note¹: ..
Note²: an IPv4 address represented by a tuple of 4 integers (between 0 and 255 inclusive.)
Note³: These tuples are subject to change in the future to a more convenient data type. Please refer to the RSBAC documentation in the meantime to figure the meaning of each items.
Note: The default network object doesn't have any attributes. Moreover, network object cannot be represented from userland. Thus, attributes for this target is not supported by the rsbac Python package.
This class attribute gives access to all the RC type which are specific to the corresponding objects. It's a dict-like object.
For example, to obtain the RC Type 2 of the target FD, you could use rsbac.objects.FD.rcTypes[2]. It also works if you've an instance of the FD class in which case you could use rsbac.objects.FD('/some/path').rcTypes[2], since rcTypes is a class attribute (not specific to an instance.)
This dict-like attribute gives access to ACL entries for an object against a particular subject.
The entries are represented by a couple (requests,ttl) where requests is of type AclRequestVector and ttl is as described in the data section.
As a convenience, it is possible to the set the entry to just request, in which case an unlimited TTL is implied.
For example, to obtain the ACL entry where:
file = rsbac.objects.FD('/some/path') user = rsbac.objects.User(0)
you simply use file.acl[user] to read and write the entry on FD object /some/path for the subject User(0) (the root user in this case.)
To access effective values, there is also an eff_acl attribute.
RSBAC can optionnaly manage the Unix users and groups from inside the kernel (rather than relying on method such as the use of files /etc/passwd and /etc/group.) The rsbac.um package provides the API to manage these users and groups.
Note that the class um.User is not the same as objects.User! The former is to manage settings related to the user as stored in RSBAC, while the latter is to manage behavior of an Unix user to a RSBAC system. FIXME: Not clear.
The module also provides two dict-like variables named users and groups. They contain the list of users and groups currently registered.
class User(uid)
Create an instance which represent the user with UID uid.
__int__()
__long__()
Cast the instance to an integer which is the user's UID.
name
This read/write property is the name of the user. It is the shortname, usually called the login name.
fullname
This read/write property is the full user name. Only useful for some tools.
hashedPassword
This read/write property is the hashed password of the user. This value is only useful for backup purpose, since it is not possible to deduce the clear password from it. And it is not recommended to set the hashed password by hand. Use the password property instead.
password
This write-only property is the user password. Since the password is stored with a cryptographic hash, it is not possible to retrieve the original password from this property.
homeDirectory
This read/write property is the path to the user home directory.
shell
This read/write property is the path to the user shell.
group
This read/write property is the GID of the main group for this user. It should not be confused with the groups attribute.
groups
This set-like attribute hold the set of extra groups to which the user belong. It should not be confused with the group property.
exists
This read-only property is True if the user exists and False otherwise.
ttl
This read-write property is the TTL (time to live) in seconds for this user.
Additionnaly, there is two methods:
updatePassword(old,new)
Update the user password the usual way. The old password should be the actual password, and the new password is the password to set. This method is available to the owner of the account, while the password property is only settable by a security officer.
delete()
Remove the account from the UM configuration.
class Group(gid)
Create an instance which represent the user with GID gid.
__int__()
__long__()
Cast the instance to an integer which is the group's GID.
name
This read/write property is the name of the group.
hashedPassword
This read/write property is the hashed password of the group. This value is only useful for backup purpose, since it is not possible to deduce the clear password from it. And it is not recommended to set the hashed password by hand. Use the password property instead.
password
This write-only property is the group password. Since the password is stored with a cryptographic hash, it is not possible to retrieve the original password from this property.
ttl
This read/write property is the TTL (time to live) in seconds for this group.
members
This read-only property is a tuple which contains the um.User which belong to this groups.
extraMembers
This read-only property is a tuple which contains the um.User which have this group as an extra group.
exists
This read-only property is True if the group exists and False otherwise.
Additionnaly, there is two methods:
updatePassword(old,new)
Update the group password the usual way. The old password should be the actual password, and the new password is the password to set. This method is available to the members of the group, while the password property is only settable by a security officer.
delete()
Remove the group from the UM configuration.
The module rsbac.acl allows to manage the ACL groups. There is a dict-like variable named acl.groups which contains all the existing ACL groups.
ACL groups are represented with the following class:
Group(id)
Create an instance to represent the ACL group with ID id.
name
This read/write property is the name of the group.
members
This TTL dict-like attribute give access to the members of the group.
owner
This read/write property is the owner of the group, represented by an objects.User instance.
private
This read/write property is a boolean which indicate if the type is private (True) or global (False).
The rsbac.acl module also provides some additionnal utility functions related to ACL:
grant(subject, object, requests)
Grant requests to the subject for the given object. The TTL is kept unchanged.
revoke(subject, object, requests)
Revoke requests to the subject for the given object. The TTL is kept unchanged.
The module rsbac.rc allows to manage RC Roles and RC Types.
Type(..)
This class is not meant to be instanciated by the user. Use the various rcTypes class attribute instead.
__int__()
__long__()
Cast the RC Type to the corresponding type ID. (But note that a RC type is fully qualified by a couple (target,id). So the value returned is not sufficient to uniquely identify the RC type.)
name
This read/write property is the name of the RC type.
needSecureDelete
This read/write property is a boolean which indicate if secure deletion is required for objects with this type. Note that secure deletion is not guaranteed to work with usual file systems. Be careful before trusting the behavior of this feature.
copyTo(dest)
Copy all the attribute of the RC type to another RC type (existing or not) of ID dest.
clone([name])
Clone the RC type with an optional new name (otherwise the original name is also copied.) Returns the new RC Type.
delete()
Delete the RC type from the RSBAC system. Basically it only means that the type become unnamed.
Role(id)
Create an instance to represent the RC role with ID id.
__int__()
__long__()
Cast the instance to the RC role ID.
id
This read-only property is the ID of the RC role.
name
This read/write property is the name of the RC role.
compatibility
This attribute is a TTL dict-like variable which gives access to the role compatibility.
adminRoles
This attribute is a TTL dict-like variable which gives access to the list of RC roles that can administrate this RC role. FIXME.
assignRoles
This attribute is a TTL dict-like variable which gives access to the list of RC roles that.. FIXME.
typeCompatibility
This attribute is a dict-like variable which gives access to the permission for the RC role to a given RC type.
defaultIndividualFdCreateType
This attribute is a dict-like variable which gives access to the default RC type to use when creating object for a given RC type.
bootRole
This read/write property is a True if the RC role is a boot role and False otherwise.
requireReauthentication
This read/write property is a True if the RC role require to authenticate again when switching to another role (FIXME: or when switching to this RC role?) and False otherwise.
adminType
This read/write property is the type of administrator for this RC role. It's one of the constant defined by RSBAC (0 for "No Admin", 1 for "Role Admin", 2 for "System Admin").
defaultFdCreateType
defaultUserCreateType
defaultGroupCreateType
defaultProcessCreateType
defaultProcessChownType
defaultProcessExecuteType
defaultIpcCreateType
defaultUnixsockCreateType
These eight attributes are dict-like variable which gives access to the corresponding RC type to use in the given context.
copyTo(dest)
Copy all the attribute of the RC role to another RC role (existing or not) of ID dest.
clone([name])
Clone the RC role with an optional new name (otherwise the original name is also copied.) Returns the new RC Role.
delete()
Remove the RC role from the RSBAC system.
The rsbac.rc module also provides some additionnal utility functions related to RC:
grant(role, type, requests)
Grant requests to the RC Role for the given RC Type. The TTL is kept unchanged.
revoke(role, type, requests)
Revoke requests to the RC role for the given RC type. The TTL is kept unchanged.
findUnnamedRole(start=0)
Search sequentially for a new unused RC role ID, starting from start.
findUnnamedRoles(n=1, start=0)
Search sequentially for a set of unused RC role ID up to n items, starting from start.
findRole(name,[default])
Find a role with the given name. If several roles share the same name, the one with the lowest ID is returned. If no roles is found, then default is returned if specified, otherwise an error of type IndexError is raised.
findUnnamedType(target,start=0)
Search sequentially for a new unused RC type ID, starting from start.
findUnnamedTypes(target,n=1, start=0)
Search sequentially for a set of unused RC type ID up to n items, starting from start.
findType(target,name,[default])
Find a type with the given name for the given target. If several types share the same name, the one with the lowest ID is returned. If no types is found, then default is returned if specified, otherwise an error of type IndexError is raised. See example section.
newRole(name, start=0)
Create a new RC role with the given name, whose ID is searched by starting from start.
There are also predefined RC roles and RC types in the modules rc.pseudoRoles and rc.pseudoTypes:
>>> dir( rsbac.rc.pseudoRoles ) ['__doc__', '__name__', 'inherit_parent', 'inherit_process', 'inherit_up_mixed', 'inherit_user', 'use_force_role'] >>> rsbac.rc.pseudoRoles.use_force_role <RC PseudoRole [-5] use_force_role>
>>> dir( rsbac.rc.pseudoTypes ) ['__doc__', '__name__', 'inherit_parent', 'inherit_process', 'no_chown', 'no_create', 'no_execute', 'use_fd', 'use_new_role_def_create'] >>> rsbac.rc.pseudoTypes.use_fd <RC PseudoType [-7] use_fd> >>> rsbac.rc.findType( rsbac.objects.FD , 'foo' ) <RC Type [14:99] 'foo'> >>> rsbac.rc.findType( rsbac.objects.FD , 'bar' ) IndexError: Type named 'bar' not found
All theses instances of Role and Type are singleton, meaning that you can compare them safely with the is operator.
The module rsbac.jail contains a single function:
jail(path=None, ip=None, flags=None, max_caps=None, scd_get=None, scd_modify=None)
Every arguments are optional.
path is the path to set the chroot environment. If None, then no chroot is performed.
ip is either None or an IP address (as a string or a 4-tuple of integers). (FIXME: not implemented as described, the current jail function expect an integer.) If None, then no IP restriction is applied. Otherwise, the processes inside the jail can only bind to the specified IPv4 address.
flags is a JailFlags instance (or equivalent integer.) If None, then all flags are cleared.
max_caps is a CapVector instance (or equivalent integer.) If None, then all flags are cleared.
scd_get and scd_modify are ScdVector instances (or equivalent integers.) If None, then all flags are cleared.
The function returns the ID of the newly created jail.
While testing, turn off softmode, but take care to turn on AUTH softmode before.
>>> rsbac.module.SOFTMODE <Module SOFTMODE [Enabled]> >>> rsbac.module.AUTH <Module AUTH [Enabled]> >>> rsbac.module.AUTH.softmode = True >>> rsbac.module.SOFTMODE.enabled = False >>> rsbac.module.SOFTMODE <Module SOFTMODE [Disabled]> >>> rsbac.module.AUTH <Module AUTH [Enabled,Softmode]>
>>> from rsbac import um
>>> um.users {} >>> um.groups {}
>>> secoff = um.addUser( 'secoff' , 400 , 'foobar' ) >>> secoff.fullname = 'RSBAC security officer' >>> secoff <UM User [400] 'secoff'> >>> um.users {400: <UM User [400] 'secoff'>}
>>> secoffGroup = um.addGroup( 'secoff' , 400 ) >>> secoff.group = secoffGroup # or secoff.group = 400
>>> foo = um.addUser( 'foo' ) >>> bar = um.addUser( 'bar' ) >>> um.users {400: <UM User [400] 'secoff'>, 2000: <UM User [2000] 'foo'>, 2001: <UM User [2001] 'bar'>}
>>> g1 = um.addGroup( 'g1' ) >>> g2 = um.addGroup( 'g2' )
>>> foo.group = g1 >>> bar.group = g2 >>> bar.groups.add( g1 ) >>> g1.members (<UM User [2000] 'foo'>,) >>> g1.extraMembers (<UM User [2001] 'bar'>,)
>>> print foo.ttl True # unlimited TTL >>> foo.ttl = 10 # set it to 10s [..wait..] >>> foo <UM User [2000] (9s) 'foo'> [..wait..] >>> foo <UM User [2000] (2s) 'foo'> [..wait..] >>> foo <UM User [2000] (?) undefined>
# foo already deleted because of the end of TTL >>> bar.delete() >>> g1.delete() >>> g2.delete() >>> foo <UM User [2000] (?) undefined> >>> g1 <UM Group [2000] (?) undefined>
>>> um.users {400: <UM User [400] 'secoff'>} >>> um.groups {400: <UM Group [400] 'secoff'>}
>>> from rsbac import FileFlags >>> from rsbac.objects import Directory >>> Directory( '/tmp/foo' ).ff_flags FileFlags('add_inherited') >>> Directory( '/tmp/foo' ).eff_ff_flags FileFlags() # no effective flags >>> Directory( '/tmp/foo' ).ff_flags = FileFlags( 'no_delete_or_rename' ) >>> Directory( '/tmp/foo' ).ff_flags FileFlags('no_delete_or_rename') # add_inherited was removed too >>> Directory( '/tmp/foo' ).eff_ff_flags FileFlags('no_delete_or_rename')
To make it easier to figure what I set in RSBAC, I started to build a tool similar to ls and to find.
# sec find /tmp --rc-type 17 /tmp/foo/bash # sec ls -A --rc --ff /tmp/foo !17 !17 f -------I-->---------- ????-??-?? ??:?? bash 0 m f ------N--->------N--- 0 2006-10-25 23:50 baz 0 m f -------I-->---------- 8 2006-10-26 10:40 bla 0 m f ------NI-->------N--- 0 2006-10-25 20:52 foo2 0 m f -------I-->---------- 0 2006-10-26 10:40 ick
The --rc and --ff specify which type of information to display. There is a flag for each RSBAC module that make sense for file objects.
The --rc option display RC attributes, while --ff display FF attributes (file flags.)
In the example above, the first 3 columns are the RC attributes:
The first column is the RC type of the file. A ! mean that it is the real value, while no ! mean that the value is inherited.
The second column is the RC forced type. Likewise, a ! mean that it is the real value. For special role, an abbreviation is displayed. m is for mixed inheritance, p for process inheritance and u for user inheritance.
The third column is the RC initial type. The f mean to use the forced type.
Then come a big column to represent the FF flags. The column has 2 parts. The part before the > character is the real file flags, while the part after is the effective flags. Each flags is represented by a letter, as follow:
Letter | Flags |
r | read_only |
x | execute_only |
s | search_only |
w | write_only |
S | secure_delete |
X | no_execute |
N | no_delete_or_rename |
I | add_inherited |
a | append_only |
M | no_mount |
So, in the example, we can see that the bla file have no flags except add_inherited, and there is effective flags.
FIXME: Choose only lower case letters, then represent inherited flag by an upper case (or the opposite?), thus reducing the display of the file flags.
errno is retrieved directly from the libc through ctypes. It is not portable against another libc. See the rsbac.platform module.
MAC and PM supports are missing.
Lot of things are created on module import, which render loading the rsbac module rather slow (300ms on a 1GHz machine.)
Frédéric Jolliton (pyrsbac@tuxee.net)