9.1. Permission-based Security inside the Java 2 Platform

Permission-based security is used to make access control decisions. Given a piece of code, the security mechanism ensures that it is authorized to do what it wants to do. Let's review the entities and process involved in reaching such a decision. For a complete treatment of the subject, consult Inside Java™ 2 Platform Security [24].

9.1.1. Code Source

In the Java runtime environment, the object that is under security scrutiny is an instance of a class, with security-related characteristics that are encapsulated by its code source. The code source identifies the following two aspects of a class:

  1. The origin of the class. This is represented by a URL that points to where the class was loaded. This piece of information carries weight in measuring the trustworthiness of the class: If it is loaded from a local hard disk inaccessible from the network, it is probably more secure than if it is loaded from the open Internet.

  2. The signers of the class. This information is indirectly conveyed in a set of certificates in the code source. The certificates contain the public keys of the signers, whose corresponding private keys were used to sign the class. If the certificates have been issued by a trusted certificate authority, they vouch for the fact that the public keys do belong to the signers.

The code source is represented by the java.security.CodeSource class.

9.1.2. Permission

Permission is the authority to access some resource (for example, reading or modifying certain properties) or to perform some operation (for example, shutting down the Java virtual machine and therefore terminating the application in execution). The java.security.Permission class and its subclasses are used to represent permissions. In the following example,

PropertyPermission propPerm =
      new PropertyPermission("java.vendor", "read");

propPerm represents the permission to read the java.vendor system property. Both the target resource (java.vendor system property) and how it is to be accessed (read) must be specified for this permission.

Here is another example:

RuntimePermission exitPerm = new RuntimePermission("exitVM");

exitPerm represents the permission to shut down the Java virtual machine. It only requires an operation (exitVM) to be specified; no additional parameters are needed.

The bearer of a permission is allowed to access a resource or to perform an operation specified in the permission, and the lack of it denies the caller an access or operation.

A set of permission classes have been predefined. You can create new permissions particular to your application context by extending the Permission class. The OSGi framework did exactly that by defining three new permission classes: AdminPermission, ServicePermission, and PackagePermission in the org.osgi.framework package.

A collection of permissions with the same type can be grouped into a PermissionCollection; multiple instances of PermissionCollection can be grouped into a Permissions object. As a result, a Permissions collection may hold heterogeneous permissions. These collection classes are convenient because an application class usually has many permissions, which need to be dealt with as a group.

9.1.3. Policy

There is no such thing as absolute and universal security. What is secure is determined by assumptions of trust, weighed against tolerance for risks, and balanced with cost and convenience of use. For example, possession of a bank card and its personal identification number (PIN) gives one access to cash at an automatic teller machine (ATM). It is probably more secure to require that one show a photo ID and the account information to a human to get the money, but that would increase the cost to the bank and reduce the convenience for the customer. Further restrictions on limiting the maximum amount of cash that can be withdrawn per day lowers the risk factor if one loses the card and divulges the PIN. These considerations make the ATM a secure alternative to banking in most circumstances.

Specifying who can do what is captured by a policy. The java.security.Policy class defines a configurable access control matrix. There is exactly one Policy object per Java virtual machine, and it maps the class's code source (which establishes trust) to a set of permissions that the instances of the class can have. Essentially, a policy specifies rules of the following form:

If a class is from Charles Schwab and is signed by the brokerage, allow it to access my account.

If a class is from RealNetworks, allow it to play a piece of streaming media.

If an applet class is from TurboTax, allow it to print to the printer.

The java.security.Policy class is an abstract class. Its default implementation in the Java 2 SDK is a plain text file. We look at policy file syntax shortly.

9.1.4. Granting Permissions to Classes

Permissions are not assigned directly to classes; rather, they are granted to protection domains represented by java.security.ProtectionDomain. Classes “inherit” their granted permissions by belonging to protection domains.

When a class, say Foo, is being loaded and defined by the secure class loader (a subclass of java.security.SecureClassLoader), the following will take place:

  1. The secure class loader consults the Policy object, providing it with Foo's CodeSource.

  2. Policy looks up its access control matrix according to Foo's CodeSource and returns the permissions granted to Foo.

  3. Based on Foo's CodeSource and granted permissions, the secure class loader assigns the class to the appropriate ProtectionDomain.

ProtectionDomain encapsulates a class's CodeSource and its granted permissions. Each class can only belong to one ProtectionDomain. All classes in the same ProtectionDomain are from the same CodeSource and are granted the same permissions. Figure 9.1 shows the process of granting permissions to a class.

Figure 9.1. ProtectionDomain is identified by CodeSource and granted permissions (after consulting the Policy object). The class is assigned to ProtectionDomain when it is loaded and defined by SecureClassLoader.


It is important to understand that a class's permissions have already been assigned prior to its being referenced as a type inside the Java virtual machine.

9.1.5. Security Manager

So far we have looked at one side of the coin: granting permissions. The flip side is to enforce them. A security manager performs the actual checking when a specific operation is to be carried out at run-time. It does so by examining the set of permissions owned by a calling class against the required permission. As an analogy, if the permission is a visa, then the secure class loader acts like the consulate that issues the visa, and the security manager is the customs official who verifies the visa on entry to the destination country.

If a class has the needed permission, the execution proceeds silently; otherwise, java.security.SecurityException is raised at the checkpoint.

In the Java 2 Runtime Environment, the security manager delegates permission checking to java.security.AccessController, which carries out a predefined access control algorithm. We discuss this algorithm later in “Performing Privileged Actions.”

When you develop services, you probably will not need to use classes such as CodeSource, ProtectionDomain, or SecureClassLoader, but you may need to understand how to check the caller for required permissions (Section 9.4.1) and how to perform privileged operations by asserting the permissions of your own code (Section 9.4.2).

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.143.24.22