## target: py-rsbac ## name: index *** RSBAC Python bindings *** [[TableOfContents]] = rsbac -- An Python interface to the RSBAC system = The `rsbac` package is a full interface to the [RSBAC http://rsbac.org] 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 py-rsbac-unstable-latest.tar.gz]. 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. Compatibility with 1.2.8 is not ensured. However with the correct `rsbac.headers` module, it should works. 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.) == Main functions and variables == 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. === symbolics name and documentation related functions === 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. === log related functions === `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. == Data types == === System roles === 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. === Flags === 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.. --- Example with the RequestVector type --- -=-=- >>> 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') -=-=- === dict- and set- like variables === 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. 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, `None` mean to keep the existing TTL, other value mean that the entry exists where an integer specify the TTL and `True` mean that the TTL is illimited. === TTL === 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 modules == 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. == Transactions == 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. --- Example of transaction --- -=-=- def doSomething( transaction ) : doThing1() doThing2() if not doThing3() : transaction.forget() else : doThing4() transaction.commit() withTransaction( doSomething , ttl = 300 ) -=-=- == Representing objects == 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. [[LocalTableOfContents]] === FD objects === 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` 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. === Device === 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` 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. === User and group === 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. ==== User class ==== `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` 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`. ==== Group class ==== `class Group(gid)` The `gid` in the GID of an Unix group. `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`. === Process === `class Process(pid)` The `pid` is the PID of an Unix process. `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.) === IPC === 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. === SCD === `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` 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. --- SCD instances defined in objects.system --- -=-=- >>> 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'] -=-=- === Network device === `class NetworkDevice(name)` The `name` is the network device name. `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. === Network template === `class NetworkTemplate(id)` The `id` is the ID of the RSBAC network template. `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. === Network object === `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` 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. == Details about objects properties == The following properties are part of the classes described is the previous section. === RSBAC attributes === 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. === rcTypes property === 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.) === acl property === 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.) == User management == 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. === User === `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. === Group === `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. == ACL == 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. == RC == The module `rsbac.rc` allows to manage RC Roles and RC Types. === Type === `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 === `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`. === Pseudo roles and types === There are also predefined RC roles and RC types in the modules `rc.pseudoRoles` and `rc.pseudoTypes`: --- RC pseudo roles --- -=-=- >>> 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 pseudo types --- -=-=- >>> 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 >>> rsbac.rc.findType( rsbac.objects.FD , '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. == Jail == 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. = Examples = == Module == While testing, turn off softmode, but take care to turn on AUTH softmode before. -=-=- >>> rsbac.module.SOFTMODE >>> rsbac.module.AUTH >>> rsbac.module.AUTH.softmode = True >>> rsbac.module.SOFTMODE.enabled = False >>> rsbac.module.SOFTMODE >>> rsbac.module.AUTH -=-=- == UM == --- Starting the session --- -=-=- >>> from rsbac import um -=-=- --- We start with no users and no groups --- -=-=- >>> um.users {} >>> um.groups {} -=-=- --- Add an user 'secoff' with UID 400 and password 'foobar' --- -=-=- >>> secoff = um.addUser( 'secoff' , 400 , 'foobar' ) >>> secoff.fullname = 'RSBAC security officer' >>> secoff >>> um.users {400: } -=-=- --- Add a group 'secoff' with GID 400 and set it to the 'secoff' user --- -=-=- >>> secoffGroup = um.addGroup( 'secoff' , 400 ) >>> secoff.group = secoffGroup # or secoff.group = 400 -=-=- --- Add two test accounts 'foo' and 'bar' --- -=-=- >>> foo = um.addUser( 'foo' ) >>> bar = um.addUser( 'bar' ) >>> um.users {400: , 2000: , 2001: } -=-=- --- Add two test groups 'g1' and 'g2' --- -=-=- >>> g1 = um.addGroup( 'g1' ) >>> g2 = um.addGroup( 'g2' ) -=-=- --- Set group and extra groups --- -=-=- >>> foo.group = g1 >>> bar.group = g2 >>> bar.groups.add( g1 ) >>> g1.members (,) >>> g1.extraMembers (,) -=-=- --- Change user TTL --- -=-=- >>> print foo.ttl True # unlimited TTL >>> foo.ttl = 10 # set it to 10s [..wait..] >>> foo [..wait..] >>> foo [..wait..] >>> foo -=-=- --- Remove the test accounts and test groups --- -=-=- # foo already deleted because of the end of TTL >>> bar.delete() >>> g1.delete() >>> g2.delete() >>> foo >>> g1 -=-=- --- Final state --- -=-=- >>> um.users {400: } >>> um.groups {400: } -=-=- == File flags == -=-=- >>> 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') -=-=- = Tools = 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, thus reducing the display of the file flags. = Issues = * `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.) = Authors = * Frédéric Jolliton ([pyrsbac@tuxee.net mailto:pyrsbac@tuxee.net])