Qualifier Based Protection
Semantic access rights in capabilities provide a more powerful mechanism than is found in other systems: users can positively define who can access their information and programs in a more refined way. But capabilities cannot guarantee that information is safe from attacks by cyber-criminals! For this and other purposes SPEEDOS provides a quite different mechanism, known as "qualifiers". The idea for this initially came from Keedy's programming language work, in a paper which appeared in 1997 under the name "attribute types"  and is now known as "qualifying types", or simply qualifiers. At the Timor website (https://www.timor-programming.org/) several papers can be downloaded describing various features and uses of qualifiers.
A qualifier is an instance of a type which, in addition to its normal methods, has "bracket" methods that can qualify the behaviour of a different object (the target object) with which it is associated. These are automatically activated methods (called "call-in" methods) which "catch" a call to a method of the target instance. To illustrate this, we first consider a normal call from a client object to a target object (Figure 10). At the SPEEDOS level the objects concerned are all information-hiding modules (e.g. information hiding files).
Now we add a call-in bracket method (which has been associated with the target object by its owner), see Figure 11.
The bracket method can access the parameters which the client object intended to pass to the qualified object. But it has no access to the data of either the client object or of the qualified object.
Additional code can be added before calling the qualified object (in the part of the bracket method called a prelude), see Figure 12. This code might for example access synchronising variables in the data of the qualifier, thus causing an unsynchronised qualified object to be synchronised. Or from the security viewpoint it might for example maintain a log of calls to the qualified object which can later be printed out or analysed by another computer program to detect attempts to hack the qualified object.
The code of a call-in bracket method can include a special body call, which indicates the point in the code (if any) at which the bracket method allows the call to proceed to the target method. This can appear at any point in the code of the bracket method, but may only once be called dynamically.
When the method of the qualified object has completed its task, it returns to the postlude section of the call-in method (i.e. the statements following the body call). In the postlude section it can, for example, reset the synchronisation variables. This option, which augments the code of the qualified object, is shown in Figure 12.
The call-in method can optionally let the call through, but it can also change or invalidate its parameters. A further possibility is that the call-in bracket can simply return to the caller, as is shown in Figure 13. In this case it can serve as a decoy, which can be used as a disinformation technique.
More than one qualifier can be associated with a qualified object. In this case there is a defined order such that the first is invoked as a result of a routine call from a client object, the next is then invoked if this makes a body call, etc.; a body call from the final qualifying object (if it ever happens) results in the target object being called. The postludes are executed in reverse order.
A qualifier can also have "call-out" methods . The principle of call-out bracket methods is similar to that of call-in methods, except that
- they are triggered by a call from a qualified object to some other object (the call-out object);
- a call statement (cf. the body statement for call-in methods) is used if the call-out bracket decides to pass the call on to the call-out object.
The basic concept is illustrated in Figure 14, where a qualifying object has both call-in and call-out bracket methods. However, a qualifier can be programmed to have only call-in or only call-out routines if that is appropriate.
Call-out brackets can be freely programmed to include or omit a call statement, and can optionally place it in a conditional statement.
Call-out brackets can play a significant role towards solving the confinement problem. On an individual module basis they can dynamically examine what information is being passed out of a module. They can, for example, invalidate or destroy capabilities, and they can even replace them with "false" capabilities, as a disinformation technique.
It is important that SPEEDOS qualifiers can be dynamically associated with their target modules at run-time and that these associations can be dynamically changed at any time by those with permission to do so.
At first sight it might be thought that call-out routines are superfluous, with the argument that they could be implemented as call-in brackets of the call-out object. However, this is not the case, because a call-in bracket is activated whenever the qualified object is called, while a call-out bracket is activated each time the qualified object makes a call to another object, not each time the called object is invoked. However both a client object and its qualified object can be qualified (usually, but not necessarily, by different qualifier objects), as is shown in Figure 15.
At the local object level qualifiers are managed by the compiler, but at the file level they are managed by the operating system level, i.e. by the SPEEDOS kernel. When associated with files the call-out methods are particularly significant, since these can be used to prevent information from being passed to unauthorised recipients.
Qualifiers, which can also qualify other qualifiers, give SPEEDOS very powerful tools for protecting information. In particular they provide a fine-grained solution for the access control problem  (via semantic files) and a new and precise solution for the confinement problem. The latter is usually considered as a firewall problem. However, qualifiers with call-out bracket methods provide a much more effective solution which can in effect provide flexible individual user-level firewalls for individual modules.