Java Security by Scott Oaks Here are the changes made in the 2/99 reprint: (x) 1st paragraph: Changed "Activator" to "Plugin" (xi) 2nd paragraph: Changed the last sentence to "The information in this book is based on the 1.2 FCS release." (xi) Added this paragraph: For the most part, we assume that developers using this book will be using the Java 2 platform, and our primary focus will be on the Java Development Kit (JDK) from Sun Microsystems. However, for developers using 1.1, we will provide full details of what's available in 1.1 and what has changed in Java 2; in some cases, this information has changed so radically that the information is relegated to an appendix. Complicating all of this is that while overall there are few differences between the 1.2 beta releases of the JDK and the Java 2 platform, many of those important differences occur in the security APIs. Unlike the first printing of this book, which focused on the 1.2 beta 3 release, this printing covers the API as it exists only in the Java 2 platform. (xiv) 3rd indented paragraph: Changed "(but not often used)" to "(and are deprecated)". {14} 4th and 5th paragraphs: Changed "-usepolicy" to "-Djava.security.manager" (15) sidebar, last paragraph now reads: Beginning in 1.2 beta 3, the Launcher class was incorporated into the virtual machine itself, but the syntax to use it changed in the last few beta releases. In FCS, the correct syntax is: piccolo% java -Djava.security.manager Cat /etc/passwd (23) 2nd paragraph now reads: ... and readObject() methods. The writeObject() method is responsible for writing out all data in the class; it typically uses the defaultWriteObject() method to write out all non-transient data and then its writes the transient data out in any format it desires. Similarly, the readObject() method uses the defaultReadObject() method to read the data and then must restore the corresponding transient data. It's your decision how to save and reconstitute the transient data so that its ... (23) 3rd paragraph now reads: The last clause of the last sentence should be --no data can be stored or reconstituted by any default methods. (29) 2nd paragraph: Changed "zip" to "JAR" (added to the JAR file containing...) (36) 8th paragraph: Changed "otherslocated" to "others located" Change "classes.zip" to "rt.jar" (39) After the continuation of the last paragraph on page 38 has concluded added: [Paragraph] An instance of the URLClassLoader class may also be obtained via one of these methods: [ListVariableTerm] public static URLClassLoader newInstance(URL[] urls) [filled-star dingbat] public static URLClassLoader newInstance(URL[] urls, ClassLoader parent) [filled-star dingbat] [ListVariable] Create and return a URL class loader. The difference between these methods and constructing a URL class loader directly is that the class loader returned from these methods will call the security manager's checkPackageAccess() method before it attempts to define a class; this is the optional step 2 that we referred to earlier. In 1.2, only class loaders obtained in this way will perform that optional step (unless, of course, you write your own class loader that performs that step). (39) footnote: Changed the first two sentences to: In 1.2, the URLCLassLoader class fails to handle multiple HTTP-based URLs correctly. It is hoped that this will be fixed someday; if it is not and ... (40) Deleted the final bullet on the page (the one that begins "In the URLClassLoader class, the invokeClass()..."). {41} code example The code segment incorrectly defined the jrl instance variable twice. The correct code now reads: Class self = Class.forName("JavaRunner"); JavaRunnerLoader jrl = new JavaRunnerLoader(args[0], self.getClassLoader()); ThreadGroup tg = new ThreadGroup("JavaRunner Threadgroup"); {43} To the final ListVariableTerm entry, add one new signature. Also add new text to the end of the corresponding ListVariable paragraph, so that the entire thing looks like this: protected final Class defineClass(String name, byte data[], int offset, int length) protected final Class defineClass(String name, byte data[], int offset, int length, ProtectionDomain pd) [filled-star dingbat] Create a Class object from an array ... the bytes actually define the desired class. We'll look more at protection domains in Chapter 5; if you use the signature without a protection domain, a default (system) domain will be provided for the class. {46} 2nd and 3rd paragraphs: Changed "findLocalClass()" to "findClass()" (47) last 4 paragraphs: In the last paragraph with a paragraph tag, changed "these two new methods" to "this new method" Changed both ListVariableTerm paragraphs by replacing them with this new paragraph (still a ListVariableTerm format) and changed the corresponding ListVariable paragraph to: protected final Class defineClass(String name, byte[] buf, int offset, int length, CodeSource cs) [filled-star dingbat] Define a class that is associated with the given code source. If the code source is null, this method is the equivalent of the defineClass() method in the base ClassLoader class. We'll defer showing an example of this method to Chapter 5, when we discuss code source objects. (48) Removed the ListVariableTerm entry protected CodeSource getCodeSource(URL url, Object signers[]) as well as the ListVariable paragraph immediately following it. Hence, the top of page 48 now has the continuation of the paragraph that was changed on page 47 and then the next regular paragraph: showing an example of this method to Chapter 5, when we discuss code source objects. As our first example of a class loader, ... {48-49} code example: Changed the line that reads protected Class findLocalClass(String name) { to protected Class findClass(String name) { changed the lines that read CodeSource cs = getCodeSource(urlBase, null); cl = defineClass(name, buf, 0, buf.length, cs, null); to cl = defineClass(name, buf, 0, buf.length, null); Deleted all the following lines: publc void checkPackageAccess(String name) { SecurityManager sm = System.getSecurityManager(); if (sm != null) sm.checkPackageAccess(name); } (49) 2nd and 3rd paragraphs: Changed "findLocalClass()" to "findClass()" (50) 4th paragraph Changed the middle of that paragraph so that it reads: ... even in 1.2. In 1.2 if you want to make the check for package access, you can do that by calling the checkPackageAccess() method of the security manager in the same way that we called the checkPackageDefinition() method, but that will only prevent you from access classes that aren't found by the system class loader. Alternately in 1.2, you can use the newInstance() method of the URLClassLoader class which makes such a check, or you can override the loadClass() method itself to provide such a check as we showed earlier. In 1.1, of course, you ... (50) 5th paragraph Changed "findLocalClass()" to "findClass()" Changed the last sentence to begin Note that classes loaders that are created by calling the constructor of the URLClassLoader class do not make such a call; {53-54} code example: Changed the line that reads protected Class findLocalClass(String name) { to protected Class findClass(String name) { Changed the line that reads return defineClass(name, buf, 0, buf.length, cs, null); to return defineClass(name, buf, 0, buf.length, null); {54} code fragment at the bottom of the page: Changed the lines that read url[0] = new URL("http://hr.xyz.com/"); url[1] = new URL("http://support.xyz.com/"); to urls[0] = new URL("http://hr.xyz.com/"); urls[1] = new URL("http://support.xyz.com/"); (55) paragraph continuation from page 54, add a last sentence: ... approach we've outlined above. In addition, the present implementation of the URLClassLoader will not work with multiple HTTP-based URLs, so for the present, you must write your own class loader to handle that case. {56-58} code example: Deleted the line (line 5) reading CodeSource cs; Deleted the line (line 14) reading cs = getCodeSource(urlBase, null); Changed the line reading protected Class findLocalClass(String name) { to protected Class findClass(String name) { Change the line reading cl = defineClass(name, buf, 0, buf.length, cs, null); to cl = defineClass(name, buf, 0, buf.length, null); (58) last paragraph: Changed "findLocalClass()" to "findClass()" (60) first paragraph, added the word final: public final ClassLoader getParent() [filled-star dingbat] Immediately preceeding the HeadB header (Loading resources), added the following [Paragraph] This URL class loader is known as the system class loader, and it may be retrieved via the following method: [ListVariableTerm] public static ClassLoader getSystemClassLoader() [filled-star dingbat] [ListVariable] Return the system class loader -- that is, the class loader that was used to load the base application classes. If a security manager is in place, you must have the getClassLoader runtime permission to use this method (see Chapter 5). [Paragraph] Hence, to set up a delegation class loader, you can use this call: [CodeIndent] jrl = new JavaRunnerLoader(ClassLoader.getSystemClassLoader()) [Paragraph] instead of the methods we showed earlier. (60) last few paragraphs: Changed all occurences of "getLocalResource" to "findResource" [in the ListVariableTerm and the middle of the final paragraph]. {61} 2nd set of ListVariableTerm paragraphs: Changed "getLocalResources" to "findResources". {61} Immediately before the "Summary" header, added the following: [HeadB] Loading Libraries [Paragraph] In 1.2, a new method exists in the ClassLoader class: [ListVariableTerm] protected String findLibrary(String libname) [filled-star dingbat] [ListVariable] Return the directory from which native libraries should be loaded. [Paragraph] This method is used by the System.loadLibrary() method to determine the directory in which the hative library in question should be found. If this method returns null (the default), then the native library must be in one of the directories specified by either the java.library.path or java.sys.library.path properties; typically, these properties are set in a platform-specific way (e.g. from the LD_LIBRARY_PATH on Solaris or the PATH on Windows). That mimics the behavior that applies in 1.1 and earlier releases. [Paragraph] However, a 1.2 custom class loader can override that policy and require that libraries be found in some application-define location. This prevents a user for overriding the runtime environment to specify an alternate location for that library, which offers a slight security advantage. Note that if the user can write to the hardwired directory where the library lives that this advantage no longer exists: the user can simply overwrite the existing library instead of change an environment variable to point to another library; the end result is the same. (82) Table 4-4, added as the last entry: checkPermission(Permission p) Thread.stop() Stopping a thread could corrupt state of the virtual machine. (83) After the 2nd paragraph (before the headline) added: In 1.2, the Thread class also calls the checkPermission() method of the security manager whenever the stop() method is called, since stopping a thread is an inherently dangerous operation (which has led the stop() to method become deprecated). For backward compatibility, this permission is normally granted even to untrusted classes, but an end-user may change her environment so that the security manager throws an exception whenever the stop() method is called. (84) Fixed the font for some method entries in Table 4-5. {91} In the last paragraph Changed "-usepolicy" to "-Djava.security.manager" {92} Changed the first ListVariableTerm paragraph to public CodeSource(URL url, Certificate cers[]) [filled-star dingbat] {93} Deleted the ListVariableTerm entry public final PublicKey[] getKeys() Return a copy ... (or maliciously). and replaced it with these two entries public final Certificate[] getCertificates() [filled-star dingbat] Return the array of certificates that were used to construct this code source object. The original certificates are not returned so that they cannot be modified accidentally (or mailciously). public boolean implies(CodeSource cs) [filled-star dingbat] Determine if the code source implies the parameter according to the rules of the Permission class (see later in this chapter). One code source implies another if it contains all the certificates of the parameter and if the URL of the parameter is implied by the URL of the target. Removed the 4th paragraph (the one immediately preceeding the Permissions header) and replaced it with this paragraph: In Chapter 3, we didn't bother to create code sources, which meant that our classes were assigned to a default code source. For the time being, we'll create code sources in an URL-based class loader simply based on the URL that we used to construct the class loader; these classes will all be unsigned classes as a result. In Chapter 12, we'll show how you can get the correct certificates with which to construct a code source object for a signed class. {98} In the code lines associated with list item 4, changed RuntimePermission r1 = new RuntimePermission("exit"); RuntimePermission r2 = new RuntimePermission("package.access.*"); to RuntimePermission r1 = new RuntimePermission("exitVM"); RuntimePermission r2 = new RuntimePermission("accessClassInPackage.java"); (99) Changed the last clause of the first sentence to read: "and r2 represents permission to access classes in the java package." (99) In the first paragraph under item 5 in the list, changed "topLevelWindow" to "showWindowWithoutWarningBanner"; changed "systemClipboard" to "accessClipboard", and change "eventQueue" to "accessEventQueue". In the first code line, changed "topLevelWindow" to "showWindowWithoutWarningBanner". (99) List item 6: In the first sentence of the paragraph, changed "three different classes" to "two different classes". In that paragraph, changed "Authenticator.setDefault" to "setDefaultAuthenticator" and changed "Authenticator.requestPasswordAuthentication" to "requestPasswordAuthentication". Deleted the second paragraph (the one beginning "In addition, the ability to create multicast...") altogether. Rewrote the third paragraph (the one that begins "Finally, the ability to create a listener...") as follows: In addition, this class encapsulates various URL-related permissions. Permission to specify a stream handler in the URL class is named specifyStreamHander. Deleted the first code line: NetPermission n1 = new NetPermission("multicast"); Changed the second code line to NetPermission n1 = new NetPermission("requestPasswordAuthentication"); (99-100) List item 8: Changed the third sentence from has one valid name: enableSubstitution. If granted, this permission to has two valid names: enableSubstitution and enableSubclassImplementation. The first of these permissions Then added the following sentence at the end of the paragraph: The latter permission allows the ObjectInputStream and ObjectOutputStream classes to be subclassed, which would potentially override the readObject() and writeObject() methods. (100) List item 9: Changed single name (access) to single name (supressAccessChecks) {107} In the code example Changed line 13 from if (addedAdmin && (adminMask & xyz.mask) != 0) to if (addedAdmin && (adminMask & xyz.mask) != xyz.mask) (107) Immediately before the "The Permissions Class" header, added: [Paragraph] If you implement your own PermissionCollection class, you must also keep track of whether it has been marked as read-only. There are two methods involved in this: [ListVariableTerm] public boolean isReadOnly() [filled-star dingbat] [ListTerm] Return an indication of whether the collection has been marked as read-only. [ListVariableTerm] public void setReadOnly() [filled-star dingbat] [ListTerm] Set the collection to be read-only. Once the read-only flag has been set, it cannot be unset: the collection will remain read-only forever. [Paragraph] A permission collection is expected to throw a security exception from its add() method if it has been marked as read-only. Note that the read-only instance variable is private to the PermissionCollection class, so subclasses will have to rely on the isReadOnly() method to test its value. (108) Deleted from the 5th paragraph ("In addition to the methods that are inherited...") to the "The Policy Class" header. (109) In the 7th paragraph (beginning "Getting and setting the policy"), change "Policy.getPolicy" to "getPolicy" and change "Policy.setPolicy" to "setPolicy". (109) In the 4th ListVariableTag paragraph, changed "evaluate" to "getPermissions" public abstract Permissions getPermissions(CodeSource cs) [dingbat] {109} In the final paragraph, changed "java.security.PolicyFile" to "sun.security.provider.PolicyFile". (110) In the first sentence, changed "package-protected" to "file in the sun package". (111) In the List #1 item, changed the first "-usepolicy" to "-Djava.security.policy, which must be used in conjunction with the -Djava.security.manager option." Changed the first command line to: piccolo% java -Djava.security.manager \ -Djava.security.policy=/globalfiles/java.policy Cat /etc/passwd Changed the next two "-usepolicy" to "-Djava.security.manager" [both in the ListText... paragraph between the first and second command line examples.] Changed the second command line to: piccolo% java -Djava.security.manager \ -Djava.security.policy==/globalfiles/java.policy Cat /etc/ passwd Changed the paragraph beginning "Note that you may also specify..." to "Note that you may also simply specify the -Djava.security.manager flag with no additional arguments, in which case..." Changed the third command line to: piccolo% java -Djava.security.manager Cat /etc/passwd (112) In the List paragraph tagged 3, changed "-usepolicy" to "-Djava.security.policy" (114) In the code example, immediately preceeding the final close brace, added the line: permission java.lang.RuntimePermission "stopThread"; At the end of the 1st paragraph, added the sentence: All other classes will also be able to call the stop() method on a thread. {114} Changed the ListVariableTerm paragraph from public ProtectionDomain(CodeSource cs, Permissions p) [dingbat] to public ProtectionDomain(CodeSource cs, PermissionCollection p) [dingbat] (115) The three bulleted paragraphs required the following changes: First bullet: o The defineClass() method accepts a protection domain as a parameter. In this case, the given protection domain is assigned to the class. This case is typically unused, since that method exists only in the ClassLoader class and not in the SecureClassLoader class. Second bullet: o The defineClass() method accepts a code source as a parameter. In this case, the getPermissions() method of the SecureClassLoader is used to determine the protection domain for the code source. By default, this just uses the getPermissions() class of the Policy class to find the permissions that are defined for the given code base. However, a secure class loader (including, of course, a URL class loader) has the option of overriding the getPermissions() method to enhance the set of permissions that a particular class might have. We'll see an example of this in Chapter 6, when we discuss network permissions in the class loader. Third bullet: changed "evaluate()" to "getPermissions()". {115} Changed the 2nd ListVariableTerm paragraph from public Permissions getPermissions() [dingbat] to public PermissionCollection getPermissions() [dingbat] In the associated ListVariable paragraph, change "permissions" to "permission collection". (117:) At the beginning of the fourth line, changed "Test" to "AccessTest". In figure 5-2, change "Test.init()" to "AccessTest.init()". {119} Deleted the text beginning with the paragraph starting "That facility is possible with these two methods..." through the first two paragraphs of the page 120. Replaced that section with this text: [Paragraph] That facility is possible with these two methods of the access controller class: [ListVariableTerm] public static Object doPrivileged(PrivilegedAction pa) [filled-star dingbat] [ListVariableTerm] public static Object doPrivileged(PrivilegedExceptionAction pae) [filled-star dingbat] [ListVariable] Execute the run() method of the given object, temporarily granting its permission to any protection domains that are below it on the stack. In the second case, if the embedded run() method throws an exception, the doPrivileged() method will throw a PrivilegedActionException. [Paragraph] The PrivilegedAction and PrivilegedExceptionAction interfaces contain a single method: [ListVariableTerm] public Object run() [filled-star dingbat] [ListVariable] Run the target code, which will have the permissions of the calling class. [Paragraph] The different in the two interfaces is that the run() method in the PrivilegedExceptionAction interface may throw an arbitrary exception. Note the unfortunate overloading between this method and the run() method of the Thread class and Runnable interface, which return void; a class cannot implement both the Runnable and PrivilegedAction interface. [Paragraph] The PrivilegedActionException class is a standard exception, so you must always be prepared to catch it when using the doPrivileged() method. If the embedded run() method does throw an exception, that exception will be wrapped into the PrivilegedActionException, where it may be retrieved with this call: [ListVariableTerm] public Exception getException() [ListVariable] Return the exception that was originally thrown to cause the PrivilegedActionException to be thrown. [Paragraph] Let's see how all of this might work with our network monitor example: [CodeIndent] public class NetworkMonitor { public NetworkMonitor() { try { class doSocket implements PrivilegedExceptionAction { public Object run() throws UnknownHostException, IOException { return new Socket("net.xyz.com", 4000); } }; doSocket ds = new doSocket(); Socket s = (Socket) AccessContoller.doPrivileged(ds); } catch (PrivilegedActionException pae) { Exception e = pae.getException(); if (e instanceof UnknownHostException) { // process host exception } else if (e instanceof IOException { // process IOException } else { // e must be a runtime exception throw (RuntimeException) e; } } } } [Paragraph] Two points are noteworthy here. First, the code that needs to be executed with the privileges of the NetworkMonitor class has been encapsulated into a new class -- the inner doSocket() class. [Paragraph] Second, the exception handling is somewhat new: we must list the exceptions that the socket constructor can throw in the run() method of our embedded class. If either of those exceptions is thrown, it will be encapsulated into a PrivilegedActionException and thrown back to the network monitor, where we can retrieve the actual exception with the getException() method. [Continue with the paragraph reading "Let's examine the effect these calls have" but change "these calls" to "this call". In that paragraph, also change "beginPrivileged()" to "doPrivileged()".] (120) paragraph 4: Change "beginPrivileged()" to "doPrivileged()". Changed the code example to the following: public class PayrollApp { NetworkMonitor nm; public void init() { class doInit implements PrivilegedAction { public void run() { nm = new NetworkMonitor(); } } doInit di = new doInit(); AccessContoller.doPrivileged(di); } } (121) 1st paragraph: Changed "beginPrivileged()" to "doPrivileged()". (136) 2nd paragraph: Changed "beginPrivileged()" to "doPrivileged()" [both occurances in the paragraph.] (136) 2nd-to-last paragraph: changed "in check" to "inCheck"; that word should be in Courier font. (138) 2nd paragraph now reads: In 1.2, this variable and method are deprecated. The correct operation to perform in a 1.2-based security manager is to place the calls to the InetAddress class in a class that can be used by the doPrivileged() method. In addition, the InetAddress class in 1.2 no longer calls the getInCheck() method. (139) Changed the end of the 2nd paragraph by adding the following: support machine are trusted and other classes are not. Note that if you are going to use this technique in 1.2 that it is quite possible that the class loader will not be your multi loader -- it might be one of the internal class loaders that is use to load extension or API classes. In that case, instead of throwing a security exception when the class cast fails, you should simply call the super.checkWrite() method, which will do the correct thing in 1.2. {142} code example At the beginning of the example, (as line 1), added the following private ClassLoader getNonSystemClassLoader() { Class c[] = getClassContext(); ClassLoader sys = ClassLoader.getSystemClassLoader(); for (int i = 1; i < c.length; i++) { ClassLoader cl = c[i].getClassLoader(); if (cl != null && !cl.equals(sys)) return cl; } return null; } Changed line 9 from ClassLoader loader = currentClassLoader(); to // In 1.1, use currentClassLoader() instead ClassLoader loader = getNonSystemClassLoader(); Changed lines 22 to 32 from try { AccessController.beginPrivileged(); ... } finally { AccessController.endPrivileged(); } to try { class testHost implements PrivilegedExceptionAction { String local, remote; testHost(String local, String remote) { this.local = local; this.remote = remote; } public Object run() throws UnknownHostException { InetAddress hostAddr = InetAddress.getByName(local); InetAddress remoteAddr = InetAddress.getByName(remote); if (hostAddr.equals(remoteAddr)) return new Boolean("true"); return new Boolean("false"); } } testHost th = new testHost(host, remoteHost); Boolean b = (Boolean) AccessController.doPrivileged(th); if (b.booleanValue()) return; } catch (PrivilegedActionException pae) { // Must be an UnknownHostException; continue and throw exception } (143) 2nd paragraph, the 2nd sentence now reads For a 1.1-based security manager, you would set the inCheck variable to true, execute the calls that are in the run() method of the testHost class, and then set inCheck to false. You would also need to make this method and the getInCheck() methods synchronized. (144) 1st paragraph: changed the last sentence to read In Java 1.2, you can use the doPrivileged() method of the access controller from within the class loader to attempt to open the URL. (145) 2nd paragraph: Changed the sentence In 1.2, the default behavior of the security manager is to implement the model we'll describe in this section. To In 1.2, the default behavior of the security manager is to allow the checkAccess() method to succeed in all cases unless the target thread is a member of the system thread group or the target thread group is the system thread group. In those cases, the program must have been granted a runtime permission of modifyThread or modifyThreadGroup (depending on which checkAccess() method is involved) for the operation to succeed. Hence, any thread can modify any thread or thread group except for those that belong to the system thread group. In the 3rd paragraph, deleted the phrase "this is a model implemented by the SecurityManager class in 1.2.". So the paragraph reads We'll show an example that implements a hierarchical notion of thread permissions which fits well within the notion of the virtual machine's thread hierarchy (see Figure 6-1). In ths model, a ... In the last paragraph, changed the last sentence to read The 1.2 default security manager checks for the modifyThread and modifyThreadGroup permissions as we described above. {144-145}In the code example: Changed the last paragraph of 144, the subsequent entire code example, and the first paragraph of 145 to be [Paragraph] This implementation requires us to override the getPermissions() method of the SecureClassLoader class as follows: [CodeIndent] protected PermissionCollection getPermissions(CodeSource cs) { if (!cs.equals(this.cs)) return null; Policy pol = Policy.getPolicy(); PermissionCollection pc = pol.getPermissions(cs); pc.add(new SocketPermission(urlBase.getHost(), "connect"); return pc; } [Paragraph] As long as we use the correct code source to define the class, then when the class loader resolves its permissions, the appropriate socket permission will be added to its user-defined set of permissions. (148) second paragraph: changed "two caveats" to "three caveats". Immediately preceeding the "Implementing Package Access" header, added this paragraph: Finally, remeber that in 1.2, the stop() method of the Thread class first calls the checkPermission() class of the security manager to see if the current stack has a runtime permission of "stopThread". For backward compatibility, all protection domains have that permission by default, but a particular user may be changed that in the policy file. (148) Changed the last three paragraphs (including the continuation onto page 149) to read A final area for which the default security manager is sometime inadequate is the manner in which it checks for package access and definition. In 1.1, the default security manager rejects all package access and definition attempts. In 1.2, the situation is somewhat complex. For package access, the security manager looks for a property defined in the java.security file named package.access. This property is a list of comma separated package names for which access should be checked. If the class loader uses the checkPackageAccess() method (and remember that many do not) and attempts to access a package that is in the list specified in the java.security file, then the program must have a runtime permission with a name of accessClassInPackage.. For defining a class, the operation is similar; the property name in the java.security file is package.definition and the appropriate runtime permission has a name of defineClassInPackage.. This model works well, but it requires that the java.security file and all the java.policy files be co-ordinated in their attempts to protect package access and definition. For that reason, and also to provide a better migration between releases (and because it's the only way to do it in 1.1), you may want to include the logic to process some policies within your new security manager. In that way, users will not need to make any changes on their system; in this case, the user will not have to put the appropriate RuntimePermission entries into the java.policy files by hand. {149} In the code example: Changed the entire example to read public void checkPackageAccess(String pkg) { // In 1.1, don't call the super class, which will automatically // reject the operation super.checkPackageAccess(pkg); } {150-152} Table 6-3 Changed checkAccess() [both signature] RuntimePermission("thread") to these two entries checkAccess(Thread t) RuntimePermission("modifyThread"); checkAcecss(ThreadGroup tg) RuntimePermission("modifyThreadGrou p"); Changed checkExit(int status) RuntimePermission("exit") to checkExit(int status) RuntimePermission("exitVM") Changed checkRead(FileDescriptor fd) RuntimePermission("fileDescriptor.read" ) to checkRead(FileDescriptor fd) RuntimePermission("readFileDescriptor") Changed checkWrite(FileDescriptor fd) RuntimePermission("fileDescriptor.write ") to checkWrite(FileDescriptor fd) RuntimePermission("writeFileDescriptor" ) Changed checkMulticast() [both signatures] NetPermission("multicast") to checkMulticast() [both signatures] SocketPermission(maddr.getHostAddress (), "accept,connect") Changed checkTopLevelWindow(Object w) AWTPermission("topLevelWindow") to checkTopLevelWindow(Object w) AWTPermission("showWindowWithoutWar ningBanner") Changed checkPrintJobAccess() RuntimePermission("print.queueJob") to checkPrintJobAccess() RuntimePermission("queuePrintJob") Changed checkSystemClipboardAccess() AWTPermission("systemClipboard"); to checkSystemClipboardAccess() AWTPermission("accessClipboard"); Changed checkAwtEventQueueAccess() AWTPermission("eventQueue"); to checkAwtEventQueueAccess() AWTPermission("accessEventQueue"); Changed checkPackageAccess(String pkg) RuntimePermission("package.access." + pkg) checkPackageDefinition(String pkg) RuntimePermission("package.define." + pkg) to checkPackageAccess(String pkg) RuntimePermission("accessClassInPac kage." + pkg) checkPackageDefinition(String pkg) RuntimePermission("defineClassInPac kage." + pkg) Changed checkMemberAccess(Class c, int which) RuntimePermission("reflect.declar ed." + c.getName()) to checkMemberAccess(Class c, int which) RuntimePermission("accessDeclared Members") (152) 1st bullet, changed to o The checkAccess() methods only check for the given permission if the target thread (group) is in the system thread group. (152) At the bottom of the page, added a new bullet o Thread permissions may follow the thread hierarchy rather than the default all-or-nothing policy. {153} In the code example, immediately before the last line, added public void checkAccess(Thread t) { .. follow implementation given above .. } public void checkAccess(ThreadGroup tg) { .. follow implementation given above .. } (159) 2nd-to-last paragraph: Changed "-usepolicy" to "-Djava.security.policy" [three instances.] (160) Deleted the 2nd paragraph (the one beginning "A second change") and the rest of the section through the next header ("The Secure Java Launcher"). (161) 1st paragraph: Changed "-usepolicy" to "-Djava.security.manager". At the end of the 1st paragraph, change "checkExit() method" to "checkExit(), checkPackageAccess(), and checkPackageDefinition() methods". (164) In the second to last paragraph, first line, deleted the word "is" [First we must prove that the author ...] (180) Table 8-1: Added the following lines KeyStore JKS CertificateFactory X509 SecureRandom SHA1PRNG (183) In the last paragraph before the ListVariableTerm entries, change "method" to "methods". [contain a number of useful methods we'll review here;] (184) At the end of the 2nd paragraph [after "clear, put, or remove."] added the following sentence: In 1.2, however, the argument string is clearProviderProperties, putProviderProperty, and removeProviderProperty, respectively. (190) The ListVariableTerm (for getAlgorithmProperty) now has a hollow-star dingbat. Deleted the footnote. {191} At the end of the output, added the following four lines: KeyStore.JKS CertificateFactory.X509 Alg.Alias.CertificateFactory.X.509 SecureRandom.SHA1PRNG {192} In table 8-4, replaced the middle column with the following entries: insertProvider. + provider.getName() removeProvider. + provider.getName() - not called - - not called - getProperty. + key setProperty. + key {193} 3rd paragraph: changed "three" to "six" [six new engine classes in 1.2,]. Changed "six" to "nine" [nine core Java engine classes]. In Table 8-5, added the following three rows: KeyStore KeyStoreSpi KeyStoreSpi CertificateFactory CertificateFactorySpi CertificateFactorySpi SecureRandom SecureRandomSpi SecureRandomSpi (231) The last sentence before the "The X509Certificate Class" section now reads "Fortunately, the next class allows us to import certificates." [delete "both" and "to export".] (231) Immediately preceeding the "The X509Certificate Class" section, inserted the following new section: [HeadB] The CertificateFactory class [Paragraph] If you need to import a certificate into a program, you do so by using the CertificateFactory class (java.security.cert.CertificateFactory). That class is an engine class, and it has the following interface: [ListVariableTerm] public static CertificateFactory getInstance(String type) [filled-star dingbat] [ListVariableTerm] public static CertificateFactory getInstance(String type, String provider) [filled-star dingbat] [ListVariable] Return a certificate factory that may be used to import certificates of the specified type (optionally implemented by the given provider). A CertificateException will be thrown if the given factory cannot be found or created; if the given provider is not found, a NoSuchProviderException will be thrown. The default Sun security provider has one certificate factory that works with certificates to type X509. [ListVariableTerm] public String getProvider() [filled-star dingbat] [ListTerm] Return the provider that implemented this factory. [ListVariableTerm] public String getType() [filled-star dingbat] [ListTerm] Return the type of certificates that this factory can import. [ListVariableTerm] public final Certificate generateCertificate(InputStream is) [filled-star dingbat] [ListTerm] Return a certificate that has been read in from the specified input steram. For the default Sun security provider, the input stream must be an X509 certificate in RFC 1421 format (that is, a DER-encoded certificate that has been translated into 7-bit ASCII characters); this is the most common format for transmission of X509 certificates. [ListVariableTerm] public final Collection generateCertificates(InputStream is) [filled-star dingbat] [ListTerm] Return a collection of certificates that have been defined in the given input stream. For the default Sun provider, the input stream in this case may have a single RFC 1421 formatted certificate, or it may contain a certificate chain in PKCS#7 format. [ListVariableTerm] public final CRL generateCRL(InputStream is) [filled-star dingbat] [ListTerm] Define a certificate revocation list from the data in the input stream. [ListVariableTerm] public final Collection generateCRLs(InputStream is) [filled-star dingbat] [ListTerm] Define a collection of CRLs from the data in the input stream. [Paragraph] Note that the CertificateFactory class cannot generate a new certificate -- it may only import a certificate found in a file. This is one reason why its hard to provide a certificate authority based solely on the standard Java API. In the next section, we'll see an example of reading a certificate through this interface. [Paragraph] The CertificateFactory is an engine class, so it has a companion SPI class -- the CertificateFactorySpi class -- that can be used if you want to implement your own certificate factory. Implementing such a class follows the familiar rules of engine classes: you must define a constructor that takes the type name as a parameter and then for each of the public methods listed above, you must implement a corresponding engine method with the same parameters. Certificates are complicated things, and parsing their encoding is a complicated procedure, so we won't bother showing an example of the engine class. (232) Deleted the 2nd paragraph ["The X509Certificate class looks like an engine class..."] and all the text until the last paragraph on the page that introduces the three bullets. Hence, the text reads public abstract class X509Certificate extends Certificate implements X509Extension Provide an infrastructure to support X509 version 3 formatted certificates. An X509 certificate has a number of properties... {234} code example: Changed the 5th line from X509Certificate c = X509Certificate.getInstance(fr); to CertificateFactory cf = CertificateFactory.getInstance("X509"); X509Certificate c = (X509Certificate) cf.generateCertificate(fr); (234-235) Deleted the entire section "Importing and Exporting Certificates". {237} Changed "RevokedCertificate" to "X509CRLEntry" in the last sentence of the third paragraph and the next ListVariableTerm as follows: Revoked certificates themselves are represented by the X509CRLEntry class (java.security.cert.X509CRLEntry): public abstract class X509CRLEntry implements X509Extension [dingbat] (237) Deleted the last paragraph ("Like the X509Certificate class, the X509CRL class...") and the code at the bottom of the page. (238) Deleted the first paragraph and the subsequent ListVariableTag definition. Changed the beginning of the next paragraph so that it reads Instances of the X509CRLEntry class are obtained by the getInstance() method of the CertificateFactory. Once the class has been instantiated, ... Hence, the text from 237 to 238 reads: public abstract class X509CRL implements X509Extension [dingbat] Provide the support for an X509-based certificate revocation list. Instances of the X509CRLEntry class are obtained by the getInstance() method ... (238) Deleted the ListVariableTerm (and its associated ListVariable) that reads public abstract boolean isRevoked(BigInteger serialNumber) [dingbat] Indicated whether or not ... (238) Last ListVariableTerm entry: changed "RevokedCertificate" to "X509CRLEntry": public abstract X509CRLEntry getRevokedCertificate(BigInteger bn) [dingbat] (239) Before the actual paragraph on this page ("When all is said and done,..."), inserted the following: [Paragraph] There is one more method of the X509CRL class, which it inherits from its superclass, the CRL class (java.security.cert.CRL): [ListVariableTerm] public abstract boolean isRevoked(Certificate c) [filled-star dingbat] [ListVariable] Indicate whether or not the given certificate has been revoked by this CRL. When all is said and done,... {239} Changed the code example: Changed line 5 from c = X509Certificate.getInstance(data); to CertificateFactory cf = CertificateFactory.getInstance("X509"); ByteArrayInputStream bais = new ByteArrayInputStream(data); c = (X509Certificate) cf.generateCertificate(bais); Changed lines 10-12 from X509CRL crl = X509CRL.getInstance(crlFile); BigInteger bi = c.getSerialNumber(); if (crl.isRevoked(bi)) to cf = CertificateFactory.getInstance("X509CRL"); X509CRL crl = (X509CRL) cf.generateCRL(crlFile); if (crl.isRevoked(c)) {240} code example Deleted lines 9-10 } catch (X509ExtensionException xee) { // treat as no crl (243) 2nd paragraph: Changed "Java Activator" to "Java Plug-In". Last paragraph, changed the final sentence to: The IdentityScope class has been deprecated in 1.2. (245) 4th paragraph: Changed the final sentence to read: First, however, let's take a brief look at the notion of the identity to whom a key belongs. Then added this paragraph. In Java's key management model, the association between a key and its owner is application specific. There is an Identity class in Java that was used for this purpose in 1.2, but it has been deprecated (because, among other things, it used the wrong Certificate class). However, there is still one interface that can be useful in your own applications that use keys: the Principal interface. Then deleted the Identities header and the next two paragraphs. Most of the "Identities" section must be moved into Appendix B; changes in that section will be listed later. For now, after the paragraph that was just added, keep the "Principals" subsection (make sure that the sidebar is attached to something in that section). Deleted the entire subsection "The Identity Class", and also the subsection "signers". Note that we're deleting an entire HeadA section, so the cross-reference at the beginning of the chapter must have that entry removed as well. Hence, the text flows as follows: This framework is the ultimate goal of this chapter. First, however, let's take a brief look at the notion of the identity to whom a key belongs. In Java's key management model, the association bewteen ... that use keys: the Principal interface. [Still a HeadB] Principals Classes that are concerned with identities... ... discussion of principals, ending with the 7th paragraph on page 246 ... There are other methods listed in the Principal interface -- namely ... implemented correctly for all your classes, not just those that implement the Principal interface. [HeadA -- from page 253] The KeyStore Class (246) 4th paragraph: Changed "Identity class we're about to introduce" to "the deprecated Identity class" [This paragraph is in the middle of the flow that we just discussed]. (255) In the first ListVariable term deleted "abstract": public class KeyStore [dingbat] (255) Deleted the 4th ("Although they share the features of a provider interface...") paragraph through the ListVariableTerm for the getInstance() method (plus the corresponding ListVariable paragraph). Replaced them with the following: [paragraph] The KeyStore class is an engine class; there is a corresponding KeyStoreSpi class that you can use to write your own keystore (more about that a little later). By default, the Sun security provider implements a keystore called JKS (for Java KeyStore). Hence, instances of the KeyStore class are predictable obtained via this method: [ListVariableTerm] public static final KeyStore getInstance(String type) [filled-star dingbat] [ListVariableTerm] public static final KeyStore getInstance(String type, String provider) [filled-star dingbat] [ListVariable] Return an instance of the KeyStore class that implements the given algorithm, supplied by the given provider, if applicable. In the Sun security provider, the default algorithm name is "JKS". [paragraph] If you do not want to hard-wire the name of the keystore algorithm into your application, you may use this method to return the string that should be passed to the getInstance() method: [ListVariableTerm] public static final String getDefaultType() [filled-star dingbat] [ListVariable] Return the default keystore algorithm for the enviroment. This value is obtained by looking for a property called keystore.type in the java.security file. Then continued with the paragraph "When the keystore object is created..." (255) Changed the final ListVariableTerm entry from public abstract void load(InputStream is, String password) [dingbat] to public final void load(InputStream is, char[] password) [dingbat] (256) Changed the 1st ListVariableTerm entry from public abstract void store(OutputStream os, String password) [dingbat] to public final void store(OututStream os, char[] password) [dingbat] (257) Before the 5 ListVariableTerm entries at the top of the page, added these 2 entries (so that there will be 7 ListVariableTerm entries all together): public final String getType() [filled-star dingbat] Return the name of the algorithm that this keystore implements. public final String getProvider() [filled-star dingbat] Return the name of the provider that supplied this keystore implementation. In the remaining ListVariableTerm entries on this page (5 at the top and 2 at the bottom), changed the word "abstract" to "final". (257) In the 8th paragraph (beginning with "The keystore holds two types of entries...") delete the 2nd sentence. The paragraph now reads The keystore holds two types of entries: certificate entries and key entries. A certificate entry is an entry that contains... (258) Changed the first ListVariableTerm from public abstract PrivateKey getPrivateKey(String alias, String password [dingbat] to public final Key getKey(String alias, char[] password) [dingbat] Changed the final ListVariableTerm paragraphs from public abstract void setKeyEntry(String alias, byte privateKey[], Certificate chain[]) [dingbat] public abstract void setKeyEntry(String alias, PrivateKey pk, String password, Certificate chain[]) [dingbat] to public final void setKeyEntry(String alias, byte key[], Certificate chain[]) [dingbat] public final void setKeyEntry(String alias, Key k, char[] password, Certificate chain[]) [dingbat] In all other ListVariableTerm paragraphs on this page, changed "abstract" to "final". This applies as well to the 1st ListVariableTerm paragraph on page 259. {259} code example: Changed line 4 from KeyStore ks = KeyStore.getInstance(); to KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); Changed lines 12-13 from System.out.println("The private key for " + args[0] + " is " + ks.getPrivateKey(args[0], args[1])); to char c[] = new char[args[1].length()]; args[1].getChars(0, c.length, c, 0); System.out.println("The private key for " + args[0] + " is " + ks.getKey(args[0], c)); (262) After the 1st paragraph, added the following: Implementing a keystore requires that we write a KeyStoreSpi class, just as any other engine class. For most methods in the KeyStore class, there is a corresponding abstract engine method in the KeyStoreSpi class that you must provide an implementation for. A complete list of these methods is given in Table 11-?.[simple table, 2 columns] [Table Title] Table 11-?. Engine methods in the KeyStoreSpi class [Cell Heading] KeyStore Class KeyStoreSpi class [Cell Body] aliases engineAliases containsAlias engineContainsAlias deleteEntry engineDeleteEntry getCertificate engineGetCertificate getCertificateAlias engineGetCertificateAlias getCertificateChain engineGetCertificateChain getCreationDate engineGetCreationDate getKey engineGetKey isCertificateEntry engineIsCertificateEntry isKeyEntry engineIsKeyEntry load engineLoad setCertificateEntry engineSetCertificateEntry setKeyEntry engineSetKeyEntry size engineSize store engineStore {262} 1st code example: Changed public Date getCreationDate(String alias) { to public Date engineGetCreationDate(String alias) { {262} 2nd code example (really a list of methods). Each one of these were changed by prepending the word engine to them and capitalizing the next letter (the first one changes name as well): engineGetKey() engineGetCertificateChain() engineGetCertificate() engineGetCreationDate() engineAliases() engineContainsAlias() engineSize() engineIsKeyEntry() engineIsCertificateEntry() engineGetCertificateAlias() {262} 3rd code example Changed the 1st and 2nd lines from public void setKeyEntry(String alias, PrivateKey pk, String passphrase, Certificate chain[]) to public void engineSetKeyEntry(String alias, Key key char[] passphrase, Certificate chain[]) {262} 4th code example (really a list of methods, changed as they were above): engineSetKeyEntry() engineSetCertificateEntry() engineDeleteEntry() engineStore() (262-263) final paragraph: Changed "load()" to "engineLoad()" [3 instances] {263} code example Changed the first line from public void load(InputStream is, String password) to public void engineLoad(InputStream is, char[] password) (263) 2nd paragraph, changed "load()" to "engineLoad()". {263} code example Changed the first line from public int size() to public int engineSize() (265) Removed the first code line, slightly changed the 1st paragraph, and combined the next paragraph into the 1st paragraph. In sum, the start of this section ("Installing a KeyStore class") reads like this: In order to use an alternate keystore implementation, you must install your new class into a security provider. If necessary, you'll need to establish a convention... (267) Added another ListVariableTerm and another ListVariable paragraph to the final entry on the page: public final byte[] sign() public final int sign(byte[] outbuf, int offset, int len) [filled-star dingbat] Create the digital signature... In the first of these methods, the signature is returned from the the method. Otherwise, the signature is stored into the outbuf array at the given offset, and the length of the signature is returned. If the output buffer is too small to hold the data, an IllegalArgumentException will be thrown. {269} code example Changed line 11 from KeyStore ks = KeyStore.getInstance(); to KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); Changed line 15 from PrivateKey pk = ke.getPrivateKey(args[0], args[1]); to char c[] = new char[args[1].length()]; args[1].getChars(0, c.length, c, 0); PrivateKey pk = (PrivateKey) ks.getKey(args[0], c); {270} code example Changed line 25 from KeyStore ks = KeyStore.getInstance(); to KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); {273} code example Changed lines 20-22 from X509Certificate x509 = X509Certificate.getInstance( new ByteArrayInputStream(b)); certificate = x509; to CertificateFactory cf = CertificateFactory.getInstance("X509"); certificate = cf.generateCertificate(new ByteArrayInputStream(b)); {274} 1st code example Changed lines 6-9 from KeyStore ks = KeyStore.getInstance(); ks.load(new FileInputStream( System.getProperty("user.home") + File.separator + ".keystore"), args[1]); to KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); char c[] = new char[args[1].length()]; args[1].getChars(0, c.length, c, 0); ks.load(new FileInputStream( System.getProperty("user.home") + File.separator + ".keystore"), c); Changed line 12 from PrivateKey pk = ks.getPrivateKey(args[0], args[1]); to PrivateKey pk = (PrivateKey) ks.getKey(args[0], c); {275} code example Changed line 2 from ks = KeyStore.getInstance(); to ks = KeyStore.getInstance(KeyStore.getDefaultType()); Changed line 10-27 from String signer = ks.getCertificateAlias(c); if (signer != null) { ... break; } } to try { String signer = ks.getCertificateAlias(c); if (signer != null) { System.out.println("We know the signer as " + signer); return; } for (Enumeration alias = ks.aliases(); alias.hasMoreElements(); ) { String s = (String) alias.nextElement(); try { sCert = (X509Certificate) ks.getCertificate(s); } catch (Exception e) { continue; } if (name.equals(sCert.getSubjectDN().getName())) { issuerCert = sCert; break; } } } catch (KeyStoreException kse) { throw new CertificateException("Invalid keystore"); } {279} code example Changed line 18 from protected Class findLocalClass(String name) { to protected Class findClass(String name) { Changed lines 32-35 (keep in bold) from Object ids[] = (Object []) classIds.get(urlName); CodeSource cs = getCodeSource(urlBase, ids); cl = defineClass(name, buf, 0, buf.length, cs, ids); to Certificate ids[] = (Certificate) classIds.get(urlName); CodeSource cs = new CodeSource(urlBase, ids); cl = defineClass(name, buf, 0, buf.length, cs); Deleted line 40 AccessController.beginPrivileged(); Changed lines 47-47 from CodeSource cs = getCodeSource(urlBase, null); cl = defineClass(name, buf, 0, buf.length, cs, null); to CodeSource cs = new CodeSource(urlBase, null); cl = defineClass(name, buf, 0, buf.length, cs); {280} code example Deleted lines 3-4 } finally { AccessController.endPrivileged(); {281} code example Changed lines 6-8 (keep in bold) from Object ids[] = je.getIdentities(); if (ids != null) classIds.put(className, ids); to Certificate c[] = je.getCertificates(); if (c == null) c = new Certificate[0]; classIds.put(className, c); (283) 5th ListVariableTerm entry: Added a new ListVariableTerm so that the entry looks like this: protected abstract byte[] engineSign() protected int engineSign(byte[] outbuf, int offset, int len) [filled-sta r dingbat] Create the signature based on the ... (289) 2nd paragraph: changed "early access 1.2 release of" to "early access 2 release for JDK 1.2 of" (293) Changed 1st sentence of the 3rd paragraph to read There are five new engine classes in the JCE: the Cipher, KeyAgreement, KeyGenerator, Mac, and SecretKeyFactory engines. In that paragraph, changed the 3rd sentence to read In addition to implementations of the new engines, the SunJCE security provider gives us a key factory and a key pair generator for Diffie-Hellman (DH) keys as well as a new engine for working with keystores. In Table 13-1, added the following entries Mac HmacSHA1 Mac HmacMD5 KeyStore JCEKS (294) Removed the 2nd set of ListVariableTerm entries: public interface RSAPrivateKey extends PrivateKey public interface RSAPrivateKeyCrt extends PrivateKey public interface RSAPublicKey extends PublicKey This set of interfaces ... Note that the footnote has been deleted as well. (297) To the first set of ListVariableTerm entries added the following public final void init(int strength) public final void init(int strength, SecureRandom sr) (298) To the 2nd set of ListVariableTerm entries added the following public final void engineInit(int strength, SecureRandom sr) (299) In the 3rd set of ListVariableTerm entries, deleted public class DESParamaterSpec implements AlgorithmParameterSpec but kept the DESKeySpec and the associated text. In the ListVariable paragraph, changed "These classes" to "This class". In the next ListVariable paragraph, deleted the sentence "Note that there is no corresponding parameter specification for this algorithm." (300) Replaced the ListVariableTerm entries public class RSAPrivaeKeySpec implements KeySpec public class RSAPrivateKeyCrtSpec implements KeySpec public class RSAPublicKeySpec implements KeySpec These classes implement ... with the following set of entries public class IvParameterSpec implements AlgorithmParameterSpec This class implements an initialization vector. Initialization vectors are used in many algorithms; notable in DES. public class RC2ParameterSpec implements AlgorithmParameterSpec public class RC5ParameterSpec implements AlgorithmParameterSpec These classes implement the algorithm parameter specifications for RC2 and RC5 encryption. public class SecretKeySpec implements KeySpec This class implements a key specification for the new class of secret keys. (300-301) Table 13-2 In the 2nd entry, changed "DESParameterSpec" to "IvParameterSpec" in columns 1 and 3. Replaced the final 3 entries (about RSA keys) with the following: RC2ParameterSpec byte[] getIV() RC2ParameterSpec(int effective) int getEffectiveKeyBits() RC2ParameterSpec(int effective, byte[] iv) RC2ParameterSpec(int effective, byte[] iv, int offset) RC5ParameterSpec byte[] getIV() RC5ParameterSpec(int version, int rounds, int wordSize) int getRounds() RC5ParameterSpec(int version, int rounds, int wordSize, byte[] iv) int getVersion() RC5ParameterSpec(int version, int rounds, int wordSize, byte[] iv, int offset) int getWordSize() SecretKeySpec byte[] getEncoded() SecretKeySpec(byte[] key, String Algorithm) SecretKeySpec(byte[] key, int offset, String Algorithm) (305) To the second set of ListVariableTerm entries, added the following: public final void init(int op, Key k, AlgorithmParameters ap) public final void init(int op, Key k, AlgorithmParameters ap, SecureRandom sr) (306) In the first (ListVariable) paragraph, changed "algorithm parameter specification" to "algorithm parameter specification or algorithm parameters". Changed "DESParameterSpec" to "IvParameterSpec". The whole last sentence reads In these cases, the intialization vector must be passed to the init() method within the algorithm parameter specification or algorithm parameters; the IvParameterSpec class is typically used to do this for DES encryption. {307} code example: Changed line 6 from DESParameterSpec dps = new DESParameterSpec(iv); to IvParameterSpec dps = new IvParameterSpec(iv); (309) Deleted the entire first paragraph (the one that begins "An alternate choice to using an initialization vector...). (310) In the last paragraph, changed the first occurance of the word "is" to "it": The rationale behind this system is that it allows the ... (311) In the first paragraph after the "Implementing the Cipher Class header", the first word is now "As". (312) In the 4th set of ListVariableTerm entries, added the following public void engineInit(int op, Key key, AlgorithmParameters ap, SecureRandom sr) {313} code example: Before line 18 public byte[] engineUpdate(byte in[], int off, int len) { added the following: public void engineInit(int i, Key k, AlgorithmParameters ap, SecureRandom sr) throws InvalidKeyException, InvalidAlgorithmParameterException { throw new InvalidAlgorithmParameterException( "Algorithm parameters not supported in this class"); } {317} code example: Deleted line 3 oos.close(); Deleted line 11 pw.print("XXXXXXXX"); Immediately after line 13 pw.close(); added (same indentation level) oos.writeObject(c.getIV()); oos.close(); (317) Deleted the entire 3rd paragraph (the one beginning "Note that in this example, we've sent 8 arbitrary...") {318} code example: Deleted line 9 ois.close(); Changed line 12 from c.init(Cipher.DECRYPT_MODE, key); to c.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec((byte []) ois.readObject()); (321) In the last set of ListVariableTerm entries, added one new entry; changed the other three entries, and add a sentence to the end of the ListVariable entry so that they appear as follows: public final void init(Key k) public final void init(Key k, SecureRandom sr) public final void init(Key k, AlgorithmParameterSpec aps) public final void init(Key k, AlgorithmParameterSpec aps, SecureRandom sr) Initialize the key agreement engine. The parameter specifications (if present) will vary depending upon the underlying algorithm; if the parameters are invalid, of the incorrect class, or not supported, an InvalidAlgorithmParameterException is generated. This method will also perform the first phase of the key agreement protocol. (322) Changed the first ListVariableTerm entry and its ListVariable text to: public final Key doPhase(Key key, boolean final) Execute the next phase of the key agreement protocol. Key agreement protocols usually require a set of operations to be performed in a particular order. Each operation is represented in this class by a particular phase, which usually require a key to succeed. If the provided key is not supported by the key agreement protocol, is incorrect for the current phase, or is otherwise invalid an InvalidKeyException will be thrown. The number of phases, along with the types of keys they require, vary drastically from key exchange algorithm to algorithm. Your security provider must document the types of keys required for each phase. In addition, you must specify which is the final phase of the protocol. In the next set of entries, in the 2nd ListVariable paragraph, changed "starting with a new set of calls to the doPhase() method" to "starting with a new call to the init() method". {324} code example: Changed line 18 from ka.doPhase(1, kp.getPrivate()); to ka.init(kp.getPrivate()); Changed line 28 from ka.doPhase(2, pk); to ka.doPhase(pk, true); {325} code example: Changed line 19 from ka.doPhase(1, kp.getPrivate()); to ka.init(kp.getPrivate()); Changed line 27 from ka.doPhase(2, pk); to ka.doPhase(pk, true); ka.doPhase(1, k (326) 1st paragraph: Changed 128 to 512: "a size of 512 will be better for testing." (332) Inserted as a new ListVariableTerm entry between the -storepass and -v entries -storetype type Specify the type of keystore that the keytool should operate on. This defaults to the keystore type in the java.security file, which defaults to JKS, the keystore type provided by the Sun security provider. (332) Inserted a new >ListVariableTerm entry immediately following the -storepass entry: -storetype storetype (333) Inserted a new >ListVariableTerm entry following the -noprompt entry: -trustcacerts Use the cacerts file to obtain trusted certificates from certificate authorities that have signed the certificate that is being imported. (334) Inserted a new >ListVariableTerm entry immediately following the -storepass entry: -storetype storetype [This happens twice on the page: once at the very top and once at the very bottom.] (334) In the list ListVariableTerm, changed "-csr" to "-certreq": -certreq Generate a certificate signing request... (336) In the first code example, changed "-csr" to "-certreq": piccolo% keytool -certreq -alias sdo -file sdoCSR.cer (336) Immediately preceeding the "Modifying Keystore Entries" header, added the following: We've mentioned in this section that in order to import a certificate like this that the self-signed certificate of the certificate authority must already be in the keystore. However, there's a bootstrapping issue involved in this: how do you get the initial certificates for the certificate authorities into a keystore? The JDK comes with a set of five pre-installed certificates: four from VeriSign, which issues certificates at different levels, and 1 from RSA Data, Inc. These certificates are in the cacerts file in the ${JAVAHOME}/lib/security directory. While those certificates are not present in your .keystore file, you can still import certificates into your .keystore file by using the -trustcacerts option: in that case, as long as the certificate you're importing has been signed by one of the authorities in the cacerts file, the import operation will succeed. Hence, if we'd sent our CSR request in the above example to VeriSign and the returned certificate from VeriSign was stored in the sdo.cer file, we could import it with this command: piccolo% keytool -import -file sdo.cer -alias sdo -trustcacerts If you want to use the certificates of the certificate authorities programatically, you may do so by creating a keystore of type JKS, and loading that keystore from the cacerts file. (337) Inserted a new >ListVariableTerm entry immediately following the -storepass entry: -storetype storetype [This happens twice on this page] (338) Inserted a new >ListVariableTerm entry immediately following the -storepass entry: -storetype storetype [This happens three times on this page] (339) Inserted a new >ListVariableTerm entry immediately following the -storepass entry: -storetype storetype [This happens twice on this page] (339) Before the subsection "Miscellaneous Commands", added the following subsection: [HeadB] Importing a 1.1-based Identity database [Paragraph] The keystore in 1.2 is incompatible with the identity database in 1.1, but the keytool is capable of converting between the two. To convert a 1.1 identity database to a 1.2 keystore, use this command: [ListVariableTerm, in Italics] -identitydb [ListVariable] Convert a 1.1 identity database. This command has the following options [>ListVariableTerm, in Italics] -v -keystore keystore -keypass keypass -storepass storepass -storetype storetype -file db_file [>ListVariable] The file name of the 1.1 identity database. The default for this is identitydb.obj in the user's home directory. [paragraph] With this command, each trusted entry in the identity database will be created as a key entry in the keystore. All other entries in the identity database will be ignored. (346) Changed the 2nd ListVariableTerm paragraph to: [ListVariableEntry in italics] A KeyStore type [ListVariable] You must have an entry in this file that lists the default type of keystore that an application should use. By default, that type is listed as [CodeIndent] keystore.type=jks [ListVariable] If you change the type listed in this entry, the new type will be used whenever anyone requests the default keystore implementation. {346} Changed the code associated with the 3rd ListVariableTerm entry from policy.provider=java.security.PolicyFile to policy.provider=sun.security.provider.PolicyFile (346) In the last paragraph: Changed "-usepolicy" to "-Djava.security.policy" [two occurences]. {347} 1st code line now reads -Djava.security.policy=/globals/java.policy 2nd code line now reads -Djava.security.policy==/globals/java.policy In the next ListParagraph, changed the sentence "The -usepolicy argument also initializes a security manager for the application, so you may use it by itself if you want to use only the files listed in the java.security file" to "The -Djava.security.policy argument must be used in conjunction with the -Djava.security.manager; if you want to use only the files listed in the java.security file, specify -Djava.security.manager without -Djava.security.policy.". argument, which initializes a security manager..." (347) In the 2nd ListVariableTerm entry and its associated paragraph, changed "-usepolicy" to "-Djava.security.policy" [two occurences]. (347) Deleted the 3rd and 4th ListVariableTerm entries and their associated paragraphs. The last item before the next subsection "The java.policy File" now reads "Whether or not the -Djava.security.policy argument can be used." (349) Deleted the last sentence of the 1st paragraph (the one that begins "As a result, it is not possible to upgrade..."). Changed the last sentence of the 2nd paragraph (the one that begins "In particular, although the Identity class...") to read: In addition, the Identity and IdentityScope classes have been deprecated in 1.2, so you should really move to the keystore implementation as soon as possible. The section on Identities from Chapter 11, pages 245-253, was moved into this appendix. It now starts before the section on "Identity Scopes", so that after the first two introductory paragraphs, there is the "Identity" header, the text from chapter 11, and then the "Identity Scopes" header. In addition, the text that was moved into this appendix now has some changes as well. These are listed here with reference to their original page number: (245) Deleted the 2nd paragraph of the section (the one beginning "The classes we'll examine in this section were originally designed..."). The next subsection -- the one on Principals -- remained as part of chapter 11 (including the sidebar on page 247). Hence, after the 1 introductory paragraph of this section, the next thing is the subsection entitled "The Identity Class". (246) Last ListVariableTerm ("public class Identity...") -- append a hollow-star dingbat to the end of the line. (247) Deleted the last paragraph (the one that begins "In 1.1, the Identity class is an abstract class..."). (248) 4th bullet: Deleted the sentence that begins "This features is primarily used to support the javakey...". (248) 5th bullet: Deleted the extra punctuation at the end of the sentence. (248) Deleted the sidebar "Identities and Identity Scopes" (248) Last paragraph: deleted the last clause of the last sentence, so that the last sentence reads "You're free to add that feature to your own identity class." (249) At the end of all ListVariableTerm entries, appended a hollow-star dingbat. (249) 7th ListVariableTerm entry: deleted the ListVariableTerm paragraph public void addCertificate(java.security.cert.Certificate certificate) The other ListVariableTerm (that uses java.security.Certificate) remains, as does the ListVariable paragraph. (249) 8th ListVariableTerm entry: deleted the ListVariableTerm paragraph public void removeCertificate(java.security.cert.Certificate certificate) The other ListVariableTerm (that uses java.security.Certificate) remains, as does the ListVariable paragraph. (250) 1st ListVariableTerm entry: deleted the ListVariableTerm paragraph public java.security.cert.Certificate[] getCertificates() The other ListVariableTerm (that uses java.security.Certificate) remains, as does the ListVariable paragraph. (250) Changed the first paragraph (that begins "If you have an identity object") to be this single sentence: There are two ways to obtain an identity object -- via the getIdentity() method of the IdentityScope class or by implementing and constructing an instance of your own subclass of the Identity class. (251) Deleted the first ListVariableTerm entry and its associated ListVariable paragraph. (251) In the first paragraph of the subsection "The Identity class and the security manager", deleted the first clause of the 2nd sentence ("This mechanism has changed somewhat between 1.1. and 1.2"): ... performed by untrusted classes. Table B-1 lists the methods... In the table (now Table B-1), removed the 2nd column entirely so that there is only a column for Method and one for Argument in 1.1. But change the column heading to say simply "Argument". In the next paragraph, deleted the first two words "In 1.1" and delete the final sentence (the one that begins "For example, in 1.1 a call to the..."). (252) 1st full paragraph (the one that begins "In common implementations..."): changed this paragraph to the single sentence: In common implementations of the security manager, this string is ignored and trusted classes are typically able to work with identities while untrusted classes are not. (253) Table (now Table B-2): Remove the 2nd column entirely, and changed the heading of the last column to "Parameter". In the next paragraph, deleted the words "in 1.1". After this section, continued to the section "Identity Scopes". (350) ListVariableTerm entry (public abstract class IdentityScope...): appended a hollow-star dingbat (351) For each ListVariableTerm entry, appended a hollow-star dingbat (352) 2nd-to-last paragraph: Deleted the final sentence (the one that begins "Changes in the definition of the Identity class between...") (356) 1st paragraph of the "IdentityScope and the Security Manager" section, delete the phrase 'in 1.1 and an argument of "IdentityScopre.setSystemScope" in 1.2'. In the next paragraph, deleted the two words "in 1.1". (357) 1st paragraph of the "Key Management..." section: deleted the phrase "we touched upon in Chapter 11". (365) 1st paragraph of the "Summary": deleted the last sentence (the one that begins "In the realm of Java 1.2..."). (369) Last paragraph: changed "March 1998" to "November 1998. There was an additional bug reported in July 1998 regarding the class loader, but this applied only to Netscape's implementation, not to the standard JDK." (376) In java.security.AccessController: Replaced the lines public static native void beginPrivileged(); public static native void beginPrivileged(AccessControlContext); with public static native Object doPrivileged(PrivilegedAction); public static native Object doPrivileged(PrivilegedAction, AccessControlContext); public static native Object doPrivileged(PrivilegedExceptionAction); public static native Object doPrivileged(PrivilegedExceptionAction, AccessControlContext); Deleted the line public static native void endPrivileged(); (378) In java.security.AlgorithmParameters Changed the lines // Instance Methods protected AlgorithmParameters(AlgorithmParametersSpi, Provider, String) ; to the lines // Constructors protected AlgorithmParameters(AlgorithmParametersSpi, Provider, String) ; // Instance Methods (380) In java.security.CodeSource Changed the line public CodeSource(URL, PublicKey[]); to public CodeSource(URL, Certificate[]); Changed the line public final PublicKey[] getKeys(); to public final Certificate[] getCertificates(); public boolean implies(); (383) In java.security.Identity Deleted the line public Identity(String, String, Certificate[], PublicKey); Changed the line public Certificate[] getCertificates(); to public Certificate[] certificates(); (387) In java.security.KeyPairGenerator After the line public void initialize(int); Added the lines public void initialize(int, SecureRandom); public void initialize(AlgorithmParameterSpec, SecureRandom); (388) In java.security.KeyStore Changed the line public KeyStore(); to protected KeyStore(KeyStoreSpi, Provider, String); Changed the line public static final KeyStore getInstance(); to public static final String getDefaultType(); public static KeyStore getInstance(String); public static KeyStore getInstance(String, String); Changed the line public abstract PrivateKey getPrivateKey(String, String); to public final Key getKey(String, char[]); public final Provider getProvider(); public final String getType(); Changed the line public abstract void load(InputStream, String); to public final void load(InputStream, char[]); Changed the lines public abstract void setKeyEntry(String, PrivateKey, String, Certificate[]); to public final void setKeyEntry(String, Key, char[], Certificate[]); Changed the line public abstract void store(OutputStream, char[]) to public final void store(OutputStream, char[]) Also, in every other line of this entry that has the word "abstract", changed "abstract" to "final" (392) In java.security.PermissionCollection After the line public abstract boolean implies(Permission); added the lines public boolean isReadOnly(); public void setReadOnly(); (392) In java.security.Permissions Deleted the lines public boolean isReadOnly(); public void setReadOnly(); (393) In java.security.Policy Changed the line public abstract Permissions evaluate(CodeSource); to public abstract PermissionCollection getPermissions(CodeSource); (394) In java.security.ProtectionDomain Changed the line public ProtectionDomain(CodeSource, Permissions); to public ProtectionDomain(CodeSource, PermissionCollection); Changed the line public final Permissions getPermissions(); to public final PermissionCollection getPermissions(); (395) In java.security.Provider Changed all the lines after // Instance Methods to public synchronized void clear(); public Set entrySet(); public String getInfo(); public String getName(); public double getVersion(); public Set keySet(); public synchronized void load(InputStream); public synchronized Object put(Object, Object); public synchronized void putAll(Map); public synchronized Object remove(Object); public String toString(); public Collection values(); } (396) In java.security.SecureClassLoader Changed all the lines after // Protected Instance Methods to protected final Class defineClass(String, byte[], int, int, CodeSource); protected PermissionCollection getPermissions(CodeSource); } (398) In java.security.Signature After the line public final byte[] sign(); added the line public final int sign(byte[], int, int); (399) In java.security.SignatureSpi After the line public final byte[] engineSign(); added the line public final int engineSign(byte[], int, int); (401) In java.security.UnresolvedPermission Changed the line public UnresolvedPermission(String, String, String, PublicKey); to public UnresolvedPermission(String, String, String, Certificate[]); (402) After the entry for java.security.cert.Certificate, added this new entry: Class java.security.cert.CertificateFactory A certificate factory is used to import certificates or certificate revocation lists from a file or other input stream. Class Definition public java.security.cert.CertificateFactory extends java.lang.Object { // Constructors protected CertificateFactory(CertificateFactorySpi, Provider, String); // Class Methods public static final CertificateFactory getInstance(String); public static final CertificateFactory getInstance(String, String); // Instance Methods public final CRL generateCRL(InputStream); public final Collection generateCRLs(InputStream); public final Certificate generateCertificate(InputStream); public final Collection generateCertificates(InputStream); public final Provider getProvider(); public final String getType(); } See also: X509Certificate, X509CRLEntry (402) In java.security.cert.RevokedCertificate First, the name of this entry has been changed to java.security.cert.X509CRLEntry (and it moved to its correct place in alphabetical order, which is after X509CRL). Then, after the line public abstract boolean hasExtensions(); added the line public abstract boolean hasUnsupportedCriticalExtension(); (403) In java.security.cert.X509Certificate Removed the lines // Class Methods public static final X509Certificate getInstance(InputStream); public static final X509Certificate getInstance(byte[]); Removed the line public abstract boolean hasUnsupportedCriticalExtension(); (404) In java.security.cert.X509CRL Removed the lines // Class Methods public static final X509CRL getInstance(InputStream); public static final X509CRL getInstance(byte[]); Changed the lines public abstract RevokedCertificate getRevokedCertificate(BigInteger); to public abtract X509CRLEntry getRevokedCertificate(BigInteger); After the line public abstract int getVersion(); added the line public abstract boolean hasUnsupportedCriticalExtension(); In the See Also section, changed "RevokedCertificate" to "X509CRLEntry". (405) In java.security.cert.X509Extension After the line public abstract Set getNonCriticalExtensionOIDs(); added the line public abstract boolean hasUnsupportedCriticalExtension(); In the See Also section, changed "RevokedCertificate" to "X509CRLEntry". (411) In javax.crypto.Cipher After the line public final int getOutputSize(int); added the line public final AlgorithmParameters getParameters(); After the lines public final void init(int, Key, AlgorithmParameterSpec, SecureRandom); added the lines public final void init(int, Key, AlgorithmParameters); public final void init(int, Key, AlgorithmParameters, SecureRandom); (413) In javax.crypto.CipherSpi After the line protected abstract byte[] engineGetIV(); added the line protected abstract int engineGetOutputSize(int); After the lines protected abstract void engineInit(int, Key, AlgorithmParameterSpec, SecureRandom); added the line protected abstract void engineInit(int, Key, AlgorithmParameters, SecureRandom); (414) In javax.crypto.KeyAgreement Changed the line public final Key doPhase(int, Key); to public final Key doPhase(Key, boolean); Changed the lines public final void init(SecureRandom); public final void init(AlgorithmParameterSpec); public final void init(AlgorithmParameterSpec, SecureRandom); to public final void init(Key); public final void init(Key, SecureRandom); public final void init(Key, AlgorithmParameterSpec); public final void init(Key, AlgorithmParameterSpec, SecureRandom); (415) In javax.crypto.KeyAgreementSpi Changed the line protected abstract Key engineDoPhase(int, Key); to protected abstract Key engineDoPhase(Key, boolean); Changed the lines protected abstract void engineInit(SecureRandom); protected abstract void engineInit(AlgorithmParameterSpec, SecureRandom); to protected abstract void engineInit(Key, SecureRandom); protected abstract void engineInit(Key, AlgorithmParameterSpec, SecureRandom); (415-416) In javax.crypto.KeyGenerator After the line public final Provider getProvider(); added the lines public final void init(int); public final void init(int, SecureRandom); (416) In javax.crypto.KeyGeneratorSpi After the line protected abstract SecretKey engineGenerateKey(); added the line protected abstract void engineInit(int, SecureRandom); (417) In javax.crypto.SealedObject After the line public final Object getObject(Cipher); added the lines public final Object getObject(Key); public final Object getObject(Key, String); (420) In javax.crypto.interfaces.RSAPrivateKey This section was renamed to java.security.interfaces.RSAPrivateKey, and the first line of its interface definition now reads public abstract interface java.security.interfaces.RSAPrivateKey It has been moved to the appropriate section on java.security.interfaces, immediately following DSAPublicKey. (420) In javax.crypto.interfaces.RSAPrivateKeyCrt Deleted this entry entirely. (420) In javax.crypto.interface.RSAPublicKey This section was renamed to java.security.interfaces.RSAPublicKey, and the first line of its interface definition now reads public abstract interface java.security.interfaces.RSAPublicKey It was moved to the appropriate section on java.security.interfaces, immediately following RSAPrivateKey. (421) In javax.crypto.spec.DESKeySpec Before the line (left a blank line before this) // Constructors added the lines // Constants public static final int DES_KEY_LEN; After the line public static boolean isParityAdjusted(byte[], int); added the line public static boolean isWeak(byte[], int); (421) In javax.crypto.spec.DESParameterSpec This entry was renamed to javax.crypto.spec.IvParameterSpec and its first line now reads public javax.crypto.spec.IvParameterSpec Changed the lines public DESParameterSpec(byte[]); public DESParameterSpec(byte[], int, int); to public IvParameterSpec(byte[]); public IvParameterSpec(byte[], int, int); Re-alphabetized this entry so that it follows DHPublicKeySpec (422) In javax.crypto.spec.DESedeKeySpec Before the line (left a blank line before this) // Constructors added the lines // Constants public static final int DES_EDE_KEY_LEN; (425) In javax.crypto.spec.RSAPrivateKeyCrtSpec Deleted this entry entirely. (426) In javax.crypto.spec.RSAPrivateKeySpec This entry was renamed to java.security.spec.RSAPrivateKeySpec and its first line was changed to public java.security.spec.RSAPrivateKeySpec In the See also list, removed RSAPrivateKeyCrtSpec It was moved into the section on java.security.spec, immediately following the PKCS8EncodedKeySpec entry. (426) In javax.crypto.spec.RSAPublicKeySpec This entry was renamed to java.security.spec.RSAPublicKeySpec and its first line was changed to public java.security.spec.RSAPublicKeySpec It was moved into the section on java.security.spec, immediately following the RSAPrivateKeySpec entry. (428-429) In java.lang.ClassLoader After the line // Class Methods added public static ClassLoader getSystemClassLoader(); Deleted the lines public URL getLocalResource(String); public Enumeration getLocalResources(String); Deleted the line public void checkPackageAccess(String); After the line protected final Class defineClass(byte[], int int); added the line protected final Class defineClass(String, byte[], int, int, ProtectionDomain); After the line protected Package definePackage(String, String, String, String, String String, String, URL); added the lines protected Class findClass(String); protected String findLibrary(String); (433) In java.net.URLClassLoader After the line public URLClassLoader(URL[], ClassLoader); added the lines public URLClassLoader(URL[]); public URLClassLoader(URL[], ClassLoader, URLStreamHandlerFactory); Changed the lines public static URL fileToURL(File); public static URL[] pathToURLs(String); to public static URLClassLoader newInstance(URL[]); public static URLClassLoader newInstance(URL[], ClassLoader); Changed the lines public URL getLocalResource(String); public Enumeration getLocalResources(String); public void invokeClass(String, String[]); public void setListener(URLClassLoader$Listener); to public URL findResource(String); public Enumeration findResources(String); public URL[] getURLs(); Changed the lines protected void checkPackageDefinition(String); protected Class defineClass(String, Resource); protected Package definePackage(String, Attributes, URL); protected Class findLocalClass(String); to protected void addURL(URL); protected Package definePackage(String, Manifest, URL); protected Class findClass(String); protected PermissionCollection getPermissions(CodeSource); (433-434)n java.rmi.RMISecurityManager Deleted all the lines after // Instance Methods except for the closing brace (434) In java.rmi.security.RMISecurityManager After the line public static Class loadClass(String); added the line public static Class loadClass(String, String);