Java Programming, Lecture Notes # 702, Revised 5/13/99.
Students in Prof. Baldwin's Advanced Java Programming classes at ACC will be responsible for knowing and understanding all of the material in this lesson beginning with the summer semester of 1999.
This lesson was originally written on May 2, 1999 and has been updated many times since then.
The purpose of this lesson is to serve as a backdrop for subsequent lessons that will deal with specific aspects of security in JDK 1.2.
I claim absolutely no expertise in the area of security. I am simply a college professor attempting to gather information about Java on one hand and present it to my students on the other. I disclaim any responsibility for any security problems that may occur as a result of anyone using any of the material in any of my tutorial lessons.
You are responsible for your own actions. With regard to security, you should study not only the material that I will present, but also material provided by others who possess expertise in the security area. Hopefully my material will be useful in getting you started in that direction.
Two good books on security published by O'Reilly & Associates are:
I highly recommend both of these books.
JDK 1.2 introduced many changes in Java relative to JDK 1.1. These changes were scattered throughout the JVM. Important security changes were made in three areas:
The following sections will briefly discuss the changes and additions made in each of these three important areas. Subsequent lessons will discuss them in more detail providing sample programs that implement the changes.
Sun refers to the new capabilities in this area as "Policy-based, easily-configurable, fine-grained access control."
The scheme is based on security policies and permissions. The user of the machine on which the JVM is running establishes permissions by creating or modifying security policy files on that machine.
How are permissions granted?
Specific permissions (such as writing to disk) are granted to specific code (such as a specific application or applet) based on the source of the code, the signer of the code, or both.
When code is loaded, it is granted permissions based on the security policy then in effect.
How are permissions initialized?
The policy that specifies which permissions are available for code from various signers/locations is initialized from an external configurable policy file. According to Sun, "Unless a permission is explicitly granted to code, it cannot access the resource that is guarded by that permission."
What code is covered by the new security policies?
Also according to Sun
"These new concepts of permission and policy enable the JDK to offer fine-grain, highly configurable, flexible, and extensible access control. Such access control can now not only be specified for applets, but also for all Java code, including applications, beans, and servlets." |
What is a permission?
A permission provides access to a system resource. An applet (or an application running with a security manager) can gain access to a system resource only if the corresponding permission has been explicitly granted to the code that is attempting the access. (Applications that run without a security manager are exempt from these security requirements.)
Are there any exceptions?
There is one important exception to this rule. Code always has permission to read files from its same (URL) location, and subdirectories of that location. It does not need explicit permission to do so.
What are security policy files, and how can you edit them?
Security policy files are text files that can be modified using any text editor, if you know the syntax. The new policytool utility can also be used to edit security policy files using a graphical interface that eliminates the need for you to know the syntax. The policytool utility provides a series of dialogs that allow you to check boxes, make selections, and enter text in fields to create or modify a policy file.
Can you grant permissions with code?
The following code creates a FilePermission object representing read access to the file named jnk in the temp directory
|
It is very important to note, however, that even though code can create such an object, creation of the object does not grant the permission. Code cannot grant permissions to itself. Only the policy file then in effect can grant a permission. The object created by the code can be used, for example, to determine if the code has the specified permission prior to trying to perform the action.
Tell me more about granting permissions
The default Policy implementation allows the security policy to be specified within one or more policy configuration files. These files specify what permissions are granted for code from specified sources.
The following entry in a policy configuration file grants code from the /baldwin/samples directory to have read access to the file /temp/jnk.
|
Note that the codebase is always specified in URL format and therefore always uses forward slashes regardless of the platform.
Where can I learn more about permission types?
The documentation for JDK 1.2 provides tables that describe the built-in JDK 1.2 permission types and discuss the risks of granting each type of permission.
The documentation also contains tables showing the methods that require permissions to be granted in order for the method to execute successfully.
Without going into detail, the permission types are as follows:
Where does the security policy originate?
A Policy object represents the security policy for a Java application environment. The source location for the policy information depends on the Policy implementation. The default Policy implementation obtains its information from static policy configuration files.
By default, the policy can be specified within one or more policy configuration files. These files specify the permissions that are allowed for code from a specified source.
As mentioned earlier, a policy file can be created or updated using a simple text editor or by using the graphical policytool utility program.
What and where are the default policy files?
By default, there is a single system-wide policy file, and optionally a single user policy file.
Operationally, the default Policy object is initialized the first time its getPermissions() method is called or whenever its refresh method is called. Note, however, that this happens automatically and it is not the responsibility of the programmer to cause the default Policy object to be initialized.
Initialization involves obtaining permission information from the policy configuration files and using this information to populate the Policy object.
So, where is the system-wide policy file located?
By default, the system-wide policy file is located at
java.home/lib/security/java.policy (Solaris)
java.home\lib\security\java.policy (Windows)
The term java.home refers to the value of the system property named "java.home". This system property specifies the directory into which the JDK was installed.
What permissions are granted by the default policy?
The default java.policy file installed with the JDK
Where is the optional user policy file located?
By default, the optional user policy file is located at
(Note the period in front of the word java.) The term user.home refers to the value of the system property named "user.home". This property specifies the user's home directory.
Given the user name baldwin, the "user.home" property value defaults to
How do the different policy files interact?
By default, the overall security policy is the sum of the permissions granted by the system policy and the user policy (and other policy files that may be incorporated). The system policy is loaded first and then the user policy is added to it.
What if I delete these policy files?
If neither policy configuration file is found (and another one is not specified), a default policy is used that is the same as the original sandbox policy. You can find information about the sandbox policy in various publications on JDK 1.1.
Where are the various defaults specified?
In addition to the individual configuration policy files, there is another static file named java.security that contains security properties. This file is located at
java.home/lib/security/java.security (Solaris)
java.home\lib\security\java.security (Windows)
The term java.home has the same meaning as before.
Among other things, this file specifies the locations of the policy configuration files described above.
Can I use more policy files?
You are allowed to specify any number of policy configuration files that will be loaded in a specified order. The locations of the policy files are specified as the values of properties (in the security properties file) whose syntax is of the form
policy.url.n=URL
where n is a number and URL is a URL specification.
The default system and user policy configuration files are specified in the security properties file as
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
Again, note the period in front of the word java for the user file. I will have more to say about the syntax ${java.home} later when I discuss Property Expansion.
Can policy files be loaded from remote URLs?
You can specify any number of URLs, including URLs of the form "http://". All of the designated policy files will be loaded in numeric order.
However, as soon as the system is unable to find one of the files, it quits reading. Therefore, if you don't have a user policy file, but do have one as number three, you need to modify the properties in the properties file or number three will never be read because number two can't be found.
Can I supplement or replace policy files at runtime?
It is also possible to specify an additional (or replacement) policy file when starting an application. This is accomplished using the following as a command line argument.
-Djava.security.policy
This argument sets the value of the "java.security.policy" property. For example, the following command
java -Djava.security.manager -Djava.security.policy=yourURL yourApp
will cause the policy file specified by yourURL to be loaded in addition to all of the policy files specified in the security properties file. If the new policy file is in the current directory, you can specify it by simply referencing its name. In that case, it isn't necessary to specify it in URL syntax.
Why include -Djava.security.policy on the command line?
The inclusion of -Djava.security.policy causes the default security manager to be installed causing the application to be subject to policy checks. This term is not required if the application installs a security manager.
How can I replace the other policy files?
As an alternative syntax, if you use (note the double equal signs)
java -Djava.security.manager -Djava.security.policy==yourURL yourApp
just the policy file that you specify will be used. The other policy files indicated in the security properties file will be ignored.
What about appletviewer security?
Another syntax is available to allow you to pass a policy file to the appletviewer utility program. The syntax is
appletviewer -J-Djava.security.policy=yourURL yourApplet
Note the -J ahead of the -D.
Can I always specify another policy file on the command line?
The security properties file specifies a property named "policy.allowSystemProperty" that is set to true in the default implementation. If you change this to false, then the value of the "-Djava.security.policy" argument on the command line will be ignored for both java and appletviewer commands.
Can I completely change the security policy implementation?
It isn't even necessary to use the default policy implementation. According to Sun
"An alternative policy class can be given to replace the default Policy implementation class, as long as the former is a subclass of the abstract Policy class and implements the getPermissions method (and other methods as necessary)." |
A thorough discussion of changing the policy implementation is beyond the scope of this document. If that is of interest to you, see the Sun documentation.
How are permissions really granted?
By default, permissions must be granted by a grant entry in a policy configuration file. A policy configuration file consists of a list of entries of two types. It may contain a single "keystore" entry and zero or more "grant" entries.
Permissions may be granted in the policy configuration file on the basis of the source of the code as a URL, or on the basis of the "signer" of the code, or both. In the latter case, the code is associated with a Digital Certificate signed by a particular entity.
What is a keystore?
As you will learn in detail in a subsequent lesson, a keystore is a special database containing two different types of security data. One type consists of private keys and their associated digital certificates that authenticate the public keys associated with the private keys.
The other type of data in the keystore consists of "trusted" certificates. These are certificates that you have previously learned to trust, which authenticate the private keys of other entities.
Each entry of either type in a keystore is keyed by a unique "alias".
The keytool utility can be used to create and administer keystores.
Why specify a keystore in a policy file?
The optional keystore specified in a policy configuration file is used to look up the public keys of the signers specified in the grant entries of the configuration file.
If any of the grant entries in the policy configuration file specify the alias of a signer, the policy configuration file must contain a keystore entry that contains the "trusted certificate" for that signer.
As of 5/2/99, JDK 1.2 allows only one keystore entry in a configuration file. Any keystore entries beyond the first one are ignored. The keystore entry can appear in the file anywhere outside the grant entries contained in the file.
How do you specify a keystore?
The syntax of a keystore entry is as follows:
|
where:
The URL can be relative to the location of the policy file, or can be specified on an absolute basis.
The keystore type defines:
Tell me about security providers
Many aspects of the keystore, along with other security features, can be customized by installing different "providers". These providers supply class libraries that provide different implementations of various algorithms, etc.
The default provider is SUN. If the keystore type is "JKS", which is the default type provided by SUN, it does not need to be specified in the keystore entry.
What is a code source?
Code that is to be executed is always considered to have come from a particular "code source". The code source includes the URL from which the code originated. (Even if it originated in a local disk file, that file is considered to be the code source with the file represented as a URL.)
The code source also includes a reference to the digital certificate(s) containing the public key(s) corresponding to the private key(s) that were used to digitally sign the code. (I will discuss these concepts at length in subsequent lessons.)
Certificates in a code source are referenced by unique alias names from the user's keystore.
What are grant entries and permission entries?
Each grant entry includes one or more "permission entries". The permission entries are preceded by optional codeBase and signedBy name/value pairs. These name/value pairs identify the code to which you want to grant the specified permissions. The combination of the codeBase and the signedBy values constitute the code source.
The basic format of a grant entry in a configuration file is as shown below
|
The items shown above that are not italicized must appear as is (case doesn't matter and some are optional). The italicized items represent variable values.
The entry must begin with the word grant. The optional signedBy value refers to the alias for a certificate stored in the keystore. The public key contained in that certificate is used to verify the digital signature on the code. According to Sun
"you grant the permission(s) to code signed by the private key corresponding to the public key in the keystore entry specified by the alias" |
This means that before you can grant the permissions to the code, you must first have installed the certificate for the signer as a trusted certificate in your keystore under the specified alias.
Are multiple signers allowed?
The signedBy value can be a comma-separated list of aliases, such as "tom,dick,harry". This means that the code must have been signed by tom AND dick AND harry.
More detailed description of the process
Sun provides the following clarification:
a statement like "Code signed by Adam" means "Code in a class file contained in a JAR file, where the JAR file was signed using the private key corresponding to the public key that appears in a keystore certificate in an entry aliased by Adam." |
What if some of the fields are omitted?
If the signedBy field is omitted, that means that anyone (or no one) could have signed the code.
The codeBase value identifies the source of code to which you will grant the specified permissions. If the codeBase is empty, it doesn't matter where the code originated.
CodeBase is a URL, not a path/file string name
A codeBase value is a URL and is not a path/file string name. It must always use forward slash characters and not backslash characters as the directory separator, regardless of the platform.
For example, if the source location for code on a Windows system is C:\baldwin\api\, then the codeBase entry in the policy file should be:
|
What about wildcard characters in codeBase?
Wildcard characters can be used in the codeBase value. The trailing characters of a codeBase value determine its exact meaning according to the following definitions:
"/*" matches all files (both class and JAR files) contained in that directory. "/-" matches all files (both class and JAR files) in the directory and recursively all files in subdirectories contained in that directory. |
What is the syntax of a permission entry?
A permission entry begins with the word permission. This is followed by the name of a permission class or type, such as java.io.FilePermission.
Many (but not all) permission types, such as java.io.FilePermission require that one or more actions be specified as a comma-separated list. For example, in the case of java.io.FilePermission, the different actions would specify the type of file access that is being granted (read, write, etc.).
Do all permission types have actions?
Other permission types, such as java.lang.RuntimePermission don't require an action list. You either have the permission specified by the "target_name" value for the permission class, or you don't. Example target names for java.lang.RuntimePermission are
What about that other signer_name?
You may have noticed that "signer_names" appears at two levels in the grant template presented earlier. Once for the code source, and once for the permission.
According to Sun
"The signedBy name/value pair for a permission entry is optional. If present, it indicates a signed permission. That is, the permission class itself must be signed by the given alias(es) in order for the permission to be granted." |
If you need to use this capability, you can find more information in the JDK 1.2 documentation.
Is the order of items in a permission entry critical?
The order of items in a permission entry must be:
An entry is terminated by a semicolon.
What about case?
Case is not significant for the identifiers (permission, signedBy, codeBase, etc.) but is significant for the permission_class_name or for any string that is passed in as a value.
Let's talk some more about the use of the Windows backslash character
The "target_name" for java.io.FilePermission is a path/file name. On a Windows system, when you specify a path/file in a string, you need to include two backslash characters for each actual backslash character in the path. (Note, however that this does not apply to the specification of a URL.) If you've done much in the way of programming on a Windows system, you have probably encountered this requirement before in other areas.
What about that Property Expansion feature encountered earlier?
The Property Expansion feature can be used in both the policy files and the security properties file.
When a string like
${some.property}
appears in one of these files, it will be expanded to the value of the matching system property.
In other words, the value from the matching system property will replace the specification of the system property. This makes it possible to write general statements such as:
permission java.io.FilePermission "${user.home}", "read";
This statement makes it possible to use the same policy file for different users on a multi-user system. With this permission, each user would be able to read files from their own home directory, but not from the home directories of other users on the same system.
A special shortcut for file separators
There is also a special shortcut notation
"${/}"
This notation is equivalent to
"${file.separator}"
This notation makes it possible to use statements such as:
permission java.io.FilePermission "${user.home}${/}*", "read";
This can help you to deal with the fact that different systems use different file separator characters (forward slash and backslash).
Property Expansion in a codeBase entry
If you use property expansion in a codeBase that always requires forward slashes, backslash characters that may be in the property will automatically be converted to forward slash characters before being included in the codeBase.
Where can you use Property Expansion?
Property expansion can be used anywhere a double-quoted string is allowed in the policy file. This includes the "signer_names", "URL", "target_name", and "action" fields
Setting the value of the "policy.expandProperties" property in the security properties file to false can disable property expansion. The default value when the JDK is installed is true.
What happens if a property can't be expanded?
If a property can't be expanded in a grant entry, permission entry, or keystore entry (perhaps because of a misspelling of the property name), that entry is simply ignored.
What about Property Expansion and the Windows double backslash requirement?
As you have seen above, you can mix property expansion and file path specifications in a string. On a Windows system that requires double backslash characters in a file path, the path outside of the required property expansion is first resolved and then any property expansion included in that string is performed.
According to Sun:
"A public-key certificate is a digitally signed statement from one entity, saying that the public key (and some other information) of another entity has some specific value." |
What is an entity?
An entity is a person, organization, program, computer, business, bank, or something else you trust to some degree.
What are public and private keys?
Public keys are numbers associated with a particular entity. They are intended to be known publicly. In particular, they are specifically meant to be known to anyone who needs to have trusted interactions with that entity.
Public keys are used for a variety of encryption purposes, and in particular are used to verify digital signatures. (Verification of digital signatures will be discussed in detail in a subsequent lesson).
Private keys are numbers, intended to be known only to the particular entity that owns them (they are supposed to be kept secret).
Private and public keys exist in pairs in public key cryptography systems. Typically a private key corresponds to exactly one public key. Data encrypted using a private key can be decrypted using the corresponding public key, and vice versa.
Private keys are used for a variety of cryptographic purposes. In particular, they are used to compute digital signatures.
What is digitally signed data?
Digitally signed data is data that has been stored with the "identity" of an entity, and a digital signature intended to prove that the entity is the source of the data. The data has been digitally signed using the entity's private key in an attempt to make it impossible (or extremely difficult) to forge or modify the data. (I will discuss how to digitally sign data in detail in a subsequent lesson.)
A digital signature is computed over some data using the private key of an entity (the signer) and can be verified using the public key of the same entity.
What is an identity?
An identity is a known way of addressing an entity. It can be a driver's license, a public key, a Unix UID, an Email address, an X.509 Distinguished Name, or anything else that will work.
What is a Certification Authority?
Public-key cryptography can be used in large-scale networks where it is impossible to guarantee that prior relationships between communicating entities have been previously established (as in military communications for example).
It is also generally not possible to guarantee that a central trusted repository will exist containing all public keys. Certificates were invented as a solution to the public key distribution problem.
On the Internet, public-key cryptography involves the use of a trusted third party known as a Certification Authority (CA) to certify the public key, identity, and some other information about an entity.
According to Sun:
"CAs are entities (e.g., businesses) that are trusted to sign (issue) certificates for other entities. It is assumed that CAs will only create valid and reliable certificates as they are bound by legal agreements. There are many public Certification Authorities, such as VeriSign, Thawte, Entrust, and so on. You can also run your own Certification Authority using products such as the Netscape/Microsoft Certificate Servers or the Entrust CA product for your organization." |
Uses for X.509 certificates
A common use of X.509 certificates is in web browsers that support the SSL (Secure Socket Layer) protocol.
SSL is a security protocol that provides privacy and authentication for network traffic such as credit card transactions. Both the browser and the web server must support SSL for it to be usable in any particular instance.
Other uses of X.509 certificates include code-signing schemes, such as signed Java ARchives, and Microsoft Authenticode.
Secure E-Mail standards, such as PEM and S/MIME, use X.509 certificates as do E-Commerce protocols, such as SET.
How can you get a certificate?
There are two basic ways to get certificates:
If you create certificates yourself (self-signed certificates) they won't always be accepted by others until you have them certified by a CA (and maybe not even then).
Inputs to the certification generation process
You will need a pair of matched public and private keys, generated using a special tool such as keytool. (The private key should be kept secret and used by you to sign data. If someone else knows your private key, they can masquerade as you.)
You need to provide information about yourself. Normally, this will include information such as your name and organizational address.
If you ask a CA to issue a certificate for you, that CA should require you to provide proof that the information is correct (but that may not happen depending on the level of the certificate).
A Certificate Signing Request (CSR)
To get a certificate from a CA, you provide your public key and information about yourself encapsulated in a Certificate Signing Request (CSR). You can generate a CSR using keytool or some other appropriate tool.
You digitally sign the CSR and send it to the CA along with your public key. When satisfied with the information, the CA will generate the certificate and return it to you.
Self-signed certificates
To generate the certificate yourself (a self-signed certificate) you will use the same information, plus the dates during which the certificate is valid, and a serial number. Then you simply create the certificate using a tool such as keytool.
X.509 certificates
I will discuss the contents and other aspects of an X.509 certificate in detail in a subsequent lesson.
Security APIs in JDK 1.2
The Certificate API, found in the java.security.cert package, includes several classes and interfaces used for dealing with certificates. I will discuss and use many of them in subsequent lessons.
The keytool program
The keytool program (also discussed in the next section) can be used to create public/private key pairs and self-signed X.509 v1 certificates. It can also be used to manage keystores.
Keys and certificates stored in a keystore can be used, along with the jarsigner program (see next section) to digitally sign your Java applications and applets.
A keystore is a protected database that holds keys and certificates. Access to a keystore is guarded by a password. Only someone who knows the password can change the password. Each private key in a keystore can also be guarded by its own password.
There are three versions of X.509 certificates. The keytool program can be used to display, import, and export X.509 v1, v2, and v3 certificates. It can also be used to generate new self-signed (v1 only) certificates.
The following security tools are provided with JDK 1.2 as executable programs:
How are the tools used?
All of these tools are command-line tools. In addition, policytool, which has a graphical user interface that eliminates the requirement to learn the detailed syntax of policy configuration files (I will discuss policy configuration files in detail in a subsequent lesson).
What do the tools replace?
The keytool and jarsigner tools replace javakey, which was an interim tool introduced in JDK 1.1.
The new tools provide more features than javakey, including the ability to protect the keystore and private keys with passwords. The new tools also provide the ability to verify signed JAR files in addition to generating them.
The new keystore architecture replaces the identity database that javakey created and managed. You can import information from an identity database into a keystore, via a keytool command.
What can I do with keytool?
Here are some of the things that you can do with keytool:
You can use the jar tool to create JAR files.
What can I do with the jar tool?
The JAR file format lets you bundle multiple files into a single archive file.
Typically a JAR file will contain the class files and auxiliary resources associated with applets and applications.
What can I do with the jarsigner tool?
When you need to "digitally sign" code, you can use the jar tool to place it in a JAR file. Then use the jarsigner tool to sign the JAR file. (You must first generate or import appropriate keys into your keystore using keytool).
You can use the jarsigner tool to
The jarsigner tool accesses a keystore created and managed by keytool, when it needs to find the private key and its associated certificate chain to use when signing a JAR file.
Who can sign JAR files?
Since accesses to the keystore and to private keys are protected by passwords, only people who know the passwords will be able to access the key and use it to sign a JAR file. The jarsigner tool prompts for needed passwords.
What can I do with policytool?
You can use policytool to create and modify the external policy configuration files that define your installation's security policy.
I will discuss policy configuration files in detail in a subsequent lesson.
The policytool program has a graphical user interface. You select buttons and other GUI components rather than typing in commands as with the other tools. Policy configuration files can also be created and edited using a simple text editor if your prefer.
-end-