The com.ms.security package contains classes used to represent two types of objects: permission objects and ISecurityRequest objects. This overview discusses Permission Objects, ISecurityRequest Objects, Using ISecurityRequest Objects to Perform Security Checks, and Implementing a Custom Permission.
This package contains the following:
A permission object is an object that specifies a set of rights that can be associated with a class. Classes that represent permission objects must implement the IPermission interface. The com.ms.security.permissions package supplies several classes that represent permission objects. Each of these classes controls the ability to perform certain operations, as described in the following table.
ClientStoragePermission | Controls access to client-side storage. |
ExecutionPermission | Controls the ability to run other programs. |
FileIOPermission | Controls the ability to read, write, and delete files. |
MultimediaPermission | Controls access to enhanced multimedia functionality. |
NetIOPermission | Controls the ability to perform networking operations. |
PrintingPermission | Controls the ability to print. |
PropertyPermission | Controls the ability to access and manipulate global system properties. |
ReflectionPermission | Controls the ability to perform reflection operations. |
RegistryPermission | Controls the ability to access the registry. |
SecurityPermission | Controls access to the java.lang.security package. |
SystemStreamsPermission | Controls the ability to change the values of system streams. |
ThreadPermission | Controls the ability to create and manipulate threads and thread groups. |
UIPermission | Controls access to enhanced user interface functionality. |
UserFileIOPermission | Controls the ability to perform user-directed file I/O. |
To associate a group of permission objects with a class, you would bundle the objects together in a set (either a PermissionDataSet or a PermissionSet) and then use SecurityClassLoader methods to associate the set of permissions with a particular class. The security system for the Microsoft VM can then examine the permissions associated with the classes on the call stack to determine which permissions are allowed in a particular context. To see an example that creates a set of permissions, puts them in a PermissionSet, and then associates the PermissionSet with a class, see the Examples section of the com.ms.security overview.
An ISecurityRequest object is an instance of a class that implements the ISecurityRequest interface. The com.ms.security.permissions package supplies classes that implement the ISecurityRequest interface. These classes represent objects that have two purposes: they identify a permission type and they also represent the parameters relevant to the permission type. The following table lists each of these classes along with the permission type that each class identifies.
ExecutionRequest | PermissionID.EXEC |
FileIORequest | PermissionID.FILEIO |
NetIORequest | PermissionID.NETIO |
PropertyAccessRequest | PermissionID.PROPERTY |
ReflectionRequest | PermissionID.REFLECTION |
RegistryRequest | PermissionID.REGISTRY |
UIAccessRequest | PermissionID.UI |
UserFileIOAccess | PermissionID.USERFILEIO |
Instances of classes that implement ISecurityRequest are passed to PolicyEngine.checkPermission(ISecurityRequest) methods to do security checks for their respective permission types. An ISecurityRequest object contains parameters that are passed to the permission's check method. For example, to check for the registry permission, you should create and pass a RegistryRequest object to the PolicyEngine.checkPermission(ISecurityRequest) method. The parameters specified by the RegistryRequest object will be passed on to the RegistryPermission.check method.
To perform a non-parameterized security check such as a check for PrintingPermission, you would simply call the PolicyEngine.checkPermission(PermissionID) method, as in the following example:
// Check to see that all of your // callers have the rights to print. PolicyEngine.checkPermission(PermissionID.PRINTING);
To perform a parameterized security check, you must past a security request object of the correct type to the PolicyEngine.checkPermission method. If the permission being checked is one of the permissions that has a corresponding ISecurityRequest object, then you should create the appropriate ISecurityRequest object and then pass it to the PolicyEngine.checkPermission(ISecurityRequest) method. The following example shows how to use a FileIORequest object to perform a security check that determines whether a file called "c:\\MyFile.txt" can be deleted:
... // Create a FileIORequest object that indicates that you // want to delete the file called "c:\\MyFile.txt". FileIORequest sreq = new FileIORequest(FileIORequest.DELETE,"c:\\MyFile.txt"); // Check to see that all of your callers // have the rights to delete that file. PolicyEngine.checkPermission(sreq); ...
For parameterized security checks for a permission that does not have a predefined ISecurityRequest class (such as ThreadPermission), you must pass to the PolicyEngine.checkPermission method the PermissionID (or the name of the permission) and an Object whose type depends on the type of permission being checked. For example, to check for ThreadPermission, you would pass PermissionID.THREAD and an Object of type Thread or ThreadGroup. In general, to find out what type of Object to pass to the checkPermission method, consult the documentation for the check method of the permission you want to check.
If a security check fails, a SecurityExceptionEx is thrown. For more information about how security checks are implemented by the Microsoft VM, see the PolicyEngine class.
There may be times when you want to implement your own permission class. As mentioned above, every permission class must implement the IPermission interface. In addition, a custom permission class may need to implement the interfaces shown in the following table.
IencodablePermission | If instances of your custom permission class need to be encoded for storage in a digital signature, your permission class should implement the IEncodablePermission interface. The IEncodablePermission interface can also be implemented to allow a user-friendly name for the class to be displayed in security dialog boxes. |
IadjustablePermission | If instances of your custom permission class need to contain context information, the permission class must implement the IAdjustablePermission interface. |
The following code shows how to implement a custom permission class called NamePermission that keeps track of names that are allowed. Notice that NamePermission implements the mandatory IPermission interface.
package MyPackage; import com.ms.security.*; public class NamePermission implements IPermission { String[] allowedNames; void setAllowedNames(String[] names) { // Copy the array of allowed names. int len = names.length; allowedNames = new String[len]; System.arraycopy(names,0,allowedNames,0,len); } void check(Object request) throws SecurityException { // See if the Object is a String. if (!(request instanceof String) ) throw new IllegalArgumentException("Illegal argument."); // See if the name is in the array of allowed names. for (int i= 0; i < allowedNames.length; i++ ) if (allowedNames[i].equals( (String)request ) ) return; // Not in the list, so throw exception. throw new SecurityException("Security check failed."); } IPermission copy() { // Create a new NamePermission object. NamePermission copy = new NamePermission(); // Initialize the copy with the // allowed names. copy.setAllowedNames(allowedNames); return copy; } IPermission combine(IPermission other) { // See if the other permission // object is of the right type. if(!(other instanceof NamePermission)) throw new IllegalArgumentException("Illegal argument."); // Create a NamePermission object. NamePermission comb = new NamePermission(); // Combine the two permission objects. comb.allowedNames = PermissionUtils.combineArraysOfStrings(this.allowedNames, ((NamePermission)other).allowedNames); // Return the combination. return comb; } int compare(IPermission other) { // if (!(other instanceof NamePermission)) throw new IllegalArgumentException("Illegal argument."); // Return the result of comparing the names // allowed by the two permission objects. return PermissionUtils.compareArraysOfStrings(this.allowedNames, ((NamePermission)other).allowedNames); } }
You could then determine whether a particular name (such as "Pat") is allowed.
// Create a security request object. String name = "Pat"; // Do the security check, passing // in the security request object. PolicyEngine.checkPermission("MyPackage.NamePermission",name);