• No results found

All Permissions

8.3 The Security Class

In this section, we'll look into how the Java VM locates the security provider(s) we want to use. The Security class (java.security.Security) is responsible for managing the set of provider classes that a Java program can use and forms the last link in the architecture of the security provider. This class is final, and all its methods are static (except for its constructor, which is private). Like the System and Math classes, then, the Security class can never be created or subclassed; it exists simply to provide a

placeholder for methods that deal with the java.security package.

Earlier, we explained how to add entries to the java.security file to add new providers to the security

architecture. The same feat can be accomplished programmatically via these methods of the Security class:

public static int addProvider(Provider provider)

Add a new provider into the list of providers. The provider is added to the end of the internal array of providers.

public static int insertProviderAt(Provider provider, int position)

Add a new provider into the internal array of providers. The provider is added at the specified position; other providers have their index changed if necessary to make room for this provider.

Position counting begins at 1.

The notion that these classes are kept in an indexed array is important; when the Security class is asked to provide a particular algorithm for an operation, the array is searched sequentially for a provider that can supply the requested algorithm for the requested operation.

As an example, let's assume the existence of an SDO security provider. This class comes with a set of classes to perform generation of key pairs, and it can generate key pairs according to two algorithms: DSA and XYZ.

The SDO class, according to an entry added to the java.security file, has been added at position 2.

Additionally, let's say that our Java program has installed an additional provider class at position 3 called JRA that can generate key pairs and digital signatures according to a single algorithm known as Foo. This leaves us with the set of provider classes listed in Table 8−3.

Table 8−3. Sample Security Providers

Now when our Java program needs to generate a key pair, the security provider is consulted as to which classes will implement the key pair generation we want. If we need to generate a DSA key, the security provider returns to us a class associated with the Sun provider class since the Sun provider, at position 1, is the first class that says that it can perform DSA key generation. If we had reversed the order of indices in the java.security file so that the Sun provider was at position 2 and the SDO provider was at position 1, a class associated with the SDO provider would have been returned instead. Similarly, when we request a Foo key pair, a class associated with the JRA provider is returned to us, regardless of what index it occurs at, since that is the only provider class that knows how to perform Foo key generation.

Remember that this is a two−step process. The security class receives a string (like KeyPairGenerator.DSA) and locates a class that provides that service (such as

sun.security.provider.Sun). The Sun class, as a provider class, does not actually know how to generate keys (or do anything else) −− it only knows what classes in the Sun security package know how to generate keys. Then the security class must ask the provider itself for the name of the class that actually implements the desired operation. That process is handled by an internal method of the Security class −−

we'll use that method implicitly over the next few chapters when we retrieve objects that implement a particular engine and algorithm. Before we do that, though, we'll finish looking at the interface of the

Security class.

There are a number of other methods in the Security class that provide basic information about the configuration of the security provider:

public static void removeProvider(String name)

Remove the named provider from the list of provider classes. The remaining providers move up in the array of providers if necessary. If the named provider is not in the list, this method silently returns (i.e., no exception is thrown).

public static Provider[] getProviders( )

Return a copy of the array of providers on which the Security class operates. Note that this is a copy of the array; reordering its elements has no effect on the Security class.

public static Provider getProvider(String name)

Return the provider with the given name. If the named provider is not in the list held by the Security class, this method returns null.

public static String getProperty(String key)

Get the property of the Security class with the associated key. The properties held in the

Security class are the properties that were read from the java.security file. In typical usage, one of the properties is security.provider.1 (as well as any other providers listed in the java.security file). Note, however, that properties of this sort may not reflect the actual order of the provider classes: when the addProvider( ), insertProviderAt( ), and removeProvider( ) methods are called, the order of the providers changes. These changes are not reflected in the internal property list.

The java.security file has a number of other properties within it; these other properties may also be retrieved via this method.

public static void setProperty(String property, String value) Set the given property to the given value.

public static String getAlgorithmProperty(String algName, String propName)

Search all the providers for a property in the form Alg.propName.algName and return the first match it finds. For example, if a provider had set the Alg.NativeImplementation.XYZ property to the string "false," a call to getAlgorithmName("XYZ",

"NativeImplementation") returns the string "false" (which is why earlier we used a string value in the provider class).

Here's a simple example, then, of how to see a list of all the security providers in a particular virtual machine:

package javasec.samples.ch08;

import java.security.*;

import java.util.*;

public class ExamineSecurity {

public static void main(String args[]) {

try {

If we run this program with the 1.3 default security providers, we get the following output (although we've removed some lines for clarity):

SUN version 1.2

Alg.Alias.KeyFactory.1.2.840.10040.4.1 Alg.Alias.Signature.1.2.840.10040.4.3

Alg.Alias.KeyPairGenerator.OID.1.2.840.10040.4.1 AlgorithmParameterGenerator.DSA

Alg.Alias.KeyPairGenerator.1.3.14.3.2.12 Alg.Alias.Signature.SHA/DSA

Alg.Alias.Signature.1.3.14.3.2.13 SecureRandom.SHA1PRNG

Alg.Alias.CertificateFactory.X.509 Alg.Alias.Signature.DSS

Signature.SHA1withDSA AlgorithmParameters.DSA MessageDigest.SHA CertificateFactory.X509

Alg.Alias.AlgorithmParameters.1.3.14.3.2.12 Alg.Alias.Signature.DSA

KeyStore.JKS

Alg.Alias.Signature.DSAWithSHA1 MessageDigest.MD5

KeyPairGenerator.DSA

Alg.Alias.Signature.SHAwithDSA

Alg.Alias.Signature.OID.1.2.840.10040.4.3 Alg.Alias.Signature.SHA1/DSA

Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1 Alg.Alias.MessageDigest.SHA−1

Alg.Alias.MessageDigest.SHA1

Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1 KeyPairGenerator.DSA KeySize

KeyFactory.DSA

Alg.Alias.Signature.1.3.14.3.2.27 Alg.Alias.Signature.SHA−1/DSA

AlgorithmParameterGenerator.DSA KeySize SunRsaSign version 1.0

Two things are readily apparent from this example. First, the strings that contain only an engine name and an algorithm implement the expected operations that we listed in Table 8−1. Second, as we mentioned in the section on the Provider class, security providers often leverage the fact that the Provider class is a subclass of the Properties class to provide properties that may make sense only to other classes that are

part of the provider package. Hence, the signature algorithm 1.3.14.3.2.13 may make sense to one of the classes in the Sun security provider, but it is not a string that will necessarily make sense to other developers.

In fact, those aliases −− including the ones that are prefaced by OID −− do have meanings within the cryptography standards world, but for our purposes we'll stick with the standard algorithm names that we listed earlier.

8.3.1 The Security Class and the Security Manager

Some of the public methods of the Security class call the checkSecurityAccess( ) method of the security manager. This gives the security manager the opportunity to intervene before an untrusted class affects the security policy of the virtual machine.

Recall that the checkSecurityAccess( ) method accepts a single string parameter. In the case of the methods in the Security class, the call that is made looks like this:

public static synchronized int

insertProviderAt(Provider provider, int position) { SecurityManager sec = System.getSecurityManager( );

if (sec != null)

sec.checkSecurityAccess("insertProvider."+provider.getName( ));

... continue to find the provider ...

}

So a program that wants to install the XYZ security provider must have been granted the

SecurityPermission named "insertProvider.XYZ". The methods of the security class that require a security permission and the names of the permission they require are listed in Table 8−4.

Table 8−4. Security Checks of the Security Class

Method Parameter

insertProviderAt( )

insertProvider. + provider.getName( )

removeProvider( )

removeProvider. + provider.getName( )

getProperty( ) getProperty. + key

setProperty( )

setProperty. + key