In its simplest form, verifying a capability involves asking the user whether the capability is (still) valid. To avoid an avalanche of questions when a high level operation triggers many low level ones, high level managers can declare roles that can contain many capabilities. Roles are either locked or unlocked; depending on their type they may require passwords to be unlocked. If a simple capability belongs to an unlocked role, it is considered valid. A capability may belong to several roles. If only one of these roles is unlocked, the capability is (potentially) valid. If not, it is invalid.
Just as there are different types of roles (that differ in they way they are unlocked, and hence provide a certain level of security), there are different types of capabilities as well. Simple capabilities are always valid (as long as they belong to an unlocked role); other capabilities may be valid only if a pass phrase was entered that has not expired yet.
The Access Control Manager does not restrict the types of roles and/or capabilities. Instead it declares two abstract classes Role and Capability that provide the core interfaces and implement the basic functionality needed to perform access control. Some fully functional (i.e. non-abstract) default roles and capabilities are declared as subclasses. The advantages of this method is that other managers can declare other types of roles or capabilities specific to their needs.
All roles store a string description describing the role, from which the user can deduce what kind of capabilities are stored in this role, and therefore which kind of actions she allows if she unlocks the role. The description is specified when creating the role.
The ACM keeps track of all roles that currently exist. These can be queried through the class method Role.getAllRoles() (which, for example, is necessary if the user wishes to lock all existing roles). When a new role is created, a reference to it is automatically added to this database of current roles. Therefore, before destroying the last external reference to a role, it must be removed from the database using the finish() method. Otherwise the reference in the database would prevent the role from being garbage collected (and it would erroneously show up in the list of all existing roles). The ACM currently implements three types of roles:
java.lang.Object | +----semper.access.Role | +----semper.access.UnlockedRole | +----semper.access.OrdinaryRole | +----semper.access.SecureRole
All capabilities store a string description describing the capability, from which the user can deduce what kind of action is associated with the capability. The description is specified when creating the capability.
Capabilities must be belong to one or more (unlocked) roles to be of any use at all. The Capability class defines the following methods to manage membership of roles:
Each capability class must specify a protected method isValid() that can be used by AccessMan to implement verifyCapability. isValid checks whether the capability is (still) valid. Depending on the type of capability that instantiates this method, this may always return true or involve the (re-)entering of a password (if it expired). This method is not accessible form outside the package (so other packages shouldn't/cannot depend on this). This implementation may change in the future.
The ACM currently implements two types of capabilities:
java.lang.Object | +----semper.access.Capability | +----semper.access.SimpleCapability | +----semper.access.PassWordCapability
verifyCapability() will check whether the capability belongs to any unlocked roles, and if so, verify whether the capability is valid. If the capability does not belong to any unlocked roles, the user is prompted to unlock one of these first. If the method is still not a member of any unlocked roles, or if the capability is not valid, verifyCapability returns false; otherwise it returns true.
verifyCapability is a static, class, method. No objects of class AccessMan need to be instantiated.
unlocked_role = new UnlockedRole("An unlocked role") ; secure_role = new SecureRole("A secure role","SECRET") ; // with password "SECRET"; unencrypted in the current implementation..Next, the manager defines two capabilities associated with the actions.
simple_capa = new SimpleCapability("Allows to say Ni!") ; password_capa = new PassWordCapability("Allows to say Ekki-ekki!","123",10000) ; // with password "123" and a timeout of 10000 milliseconds..And adds them to the roles.
simple_capa.addToRole(secure_role) ; password_capa.addToRole(unlocked_role) ;Now the original actions are guarded with the capabilities using the following piece of code.
if (AccessMan.verifyCapability(password_capa)) System.out.println("-> Ekki-ekki! ") if (AccessMan.verifyCapability(simple_capa)) System.out.println("-> Ni! ")By virtue of the first guard, the user is requested to enter the password for the capability (i.e. "123"). This capability belongs to an unlocked role; therefore the user does not have to unlock any role to enable the first action. To enable the second action, the user must unlock the secure role (i.e. with password "SECRET"). This time, nothing has to be done to make the capability valid, because it is valid by default.