1 /* 2 * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 /* @test 25 * @bug 4179055 26 * @summary Some java apps need to have access to read "accessClassInPackage.sun.rmi.server" 27 * 28 * @author Laird Dornin 29 * 30 * @library ../../../testlibrary 31 * @build TestLibrary RMID JavaVM StreamPipe ActivationLibrary 32 * @build CanCreateStubs 33 * @build StubClassesPermitted 34 * @build StubClassesPermitted_Stub 35 * @run main/othervm/policy=security.policy/secure=java.lang.SecurityManager/timeout=240 StubClassesPermitted 36 */ 37 38 import java.io.*; 39 import java.rmi.*; 40 import java.rmi.server.*; 41 import java.rmi.registry.Registry; 42 import java.rmi.activation.*; 43 import java.security.CodeSource; 44 import java.util.Properties; 45 import java.util.StringTokenizer; 46 47 /** 48 * The RMI activation system needs to explicitly allow itself to 49 * create the following sun.* classes on behalf of code that runs with 50 * user privileges and needs to make use of RMI activation: 51 * 52 * sun.rmi.server.Activation$ActivationMonitorImpl_Stub 53 * sun.rmi.server.Activation$ActivationSystemImpl_Stub 54 * sun.rmi.registry.RegistryImpl_Stub 55 * 56 * The test causes the activation system to need to create each of 57 * these classes in turn. The test will fail if the activation system 58 * does not allow these classes to be created. 59 */ 60 public class StubClassesPermitted 61 extends Activatable implements Runnable, CanCreateStubs 62 { 63 public static boolean sameGroup = false; 64 private static int registryPort = -1; 65 private static CanCreateStubs canCreateStubs = null; 66 private static Registry registry = null; 67 68 public static void main(String args[]) { 69 70 sameGroup = true; 71 72 RMID rmid = null; 73 74 System.err.println("\nRegression test for bug/rfe 4179055\n"); 75 76 try { 77 TestLibrary.suggestSecurityManager("java.lang.SecurityManager"); 78 79 registry = TestLibrary.createRegistryOnUnusedPort(); 80 registryPort = TestLibrary.getRegistryPort(registry); 81 82 // must run with java.lang.SecurityManager or the test 83 // result will be nullified if running with a build where 84 // 4180392 has not been fixed. 85 String smClassName = 86 System.getSecurityManager().getClass().getName(); 87 if (!smClassName.equals("java.lang.SecurityManager")) { 88 TestLibrary.bomb("Test must run with java.lang.SecurityManager"); 89 } 90 91 // start an rmid. 92 RMID.removeLog(); 93 rmid = RMID.createRMID(); 94 rmid.start(); 95 96 //rmid.addOptions(new String[] {"-C-Djava.rmi.server.logCalls=true"}); 97 98 // Ensure that activation groups run with the correct 99 // security manager. 100 // 101 Properties p = new Properties(); 102 p.put("java.security.policy", 103 TestParams.defaultGroupPolicy); 104 p.put("java.security.manager", 105 "java.lang.SecurityManager"); 106 107 // This action causes the following classes to be created 108 // in this VM (RMI must permit the creation of these classes): 109 // 110 // sun.rmi.server.Activation$ActivationSystemImpl_Stub 111 // sun.rmi.server.Activation$ActivationMonitorImpl_Stub 112 // 113 System.err.println("Create activation group, in a new VM"); 114 ActivationGroupDesc groupDesc = 115 new ActivationGroupDesc(p, null); 116 ActivationSystem system = ActivationGroup.getSystem(); 117 ActivationGroupID groupID = system.registerGroup(groupDesc); 118 119 System.err.println("register activatable"); 120 // Fix for: 4271615: make sure activation group runs in a new VM 121 ActivationDesc desc = new ActivationDesc 122 (groupID, "StubClassesPermitted", null, null); 123 canCreateStubs = (CanCreateStubs) Activatable.register(desc); 124 125 // ensure registry stub can be passed in a remote call 126 System.err.println("getting the registry"); 127 registry = canCreateStubs.getRegistry(); 128 129 // make sure a client cant load just any sun.* class, just 130 // as a sanity check, try to create a class we are not 131 // allowed to access but which was passed in a remote call 132 try { 133 System.err.println("accessing forbidden class"); 134 Object secureRandom = canCreateStubs.getForbiddenClass(); 135 136 TestLibrary.bomb("test allowed to access forbidden class," + 137 " sun.security.provider.SecureRandom"); 138 } catch (java.security.AccessControlException e) { 139 140 // Make sure we received a *local* AccessControlException 141 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 142 PrintStream ps = new PrintStream(bout); 143 e.printStackTrace(ps); 144 ps.flush(); 145 String trace = new String(bout.toByteArray()); 146 if ((trace.indexOf("exceptionReceivedFromServer") >= 0) || 147 trace.equals("")) 148 { 149 throw e; 150 } 151 System.err.println("received expected local access control exception"); 152 } 153 154 // make sure that an ActivationGroupID can be passed in a 155 // remote call; this is slightly more inclusive than 156 // just passing a reference to the activation system 157 System.err.println("returning group desc"); 158 canCreateStubs.returnGroupID(); 159 160 // Clean up object 161 System.err.println 162 ("Deactivate object via method call"); 163 canCreateStubs.shutdown(); 164 165 System.err.println 166 ("\nsuccess: StubClassesPermitted test passed "); 167 168 } catch (Exception e) { 169 TestLibrary.bomb("\nfailure: unexpected exception ", e); 170 } finally { 171 try { 172 Thread.sleep(4000); 173 } catch (InterruptedException e) { 174 } 175 176 canCreateStubs = null; 177 ActivationLibrary.rmidCleanup(rmid); 178 System.err.println("rmid shut down"); 179 } 180 } 181 182 static ActivationGroupID GroupID = null; 183 184 /** 185 * implementation of CanCreateStubs 186 */ 187 public StubClassesPermitted 188 (ActivationID id, MarshalledObject mo) throws RemoteException 189 { 190 // register/export anonymously 191 super(id, 0); 192 193 // obtain reference to the test registry 194 registry = java.rmi.registry.LocateRegistry. 195 getRegistry(registryPort); 196 } 197 198 /** 199 * Spawns a thread to deactivate the object. 200 */ 201 public void shutdown() throws Exception { 202 (new Thread(this,"StubClassesPermitted")).start(); 203 } 204 205 /** 206 * Thread to deactivate object. First attempts to make object 207 * inactive (via the inactive method). If that fails (the 208 * object may still have pending/executing calls), then 209 * unexport the object forcibly. 210 */ 211 public void run() { 212 ActivationLibrary.deactivate(this, getID()); 213 } 214 215 /** 216 * Return a reference to the RMI registry, to make sure that 217 * the stub for it can be deserialized in the test client VM. 218 */ 219 public Registry getRegistry() throws RemoteException { 220 if (sameGroup) { 221 System.out.println("in same group"); 222 } else { 223 System.out.println("not in same group"); 224 } 225 return registry; 226 } 227 228 /** 229 * Remote call to create and return a random serializable sun.* 230 * class, the test should get a local security exception when 231 * trying to create the class. Ensure that not all sun.* classes 232 * can be resolved in a remote call. 233 */ 234 public Object getForbiddenClass() throws RemoteException { 235 System.err.println("creating sun class"); 236 return new sun.security.provider.SecureRandom(); 237 } 238 239 /** 240 * Ensures that an activation group id can be passed in a remote 241 * call (class may contain a remote reference to the activation 242 * system implementation). 243 */ 244 public ActivationGroupID returnGroupID() throws RemoteException { 245 return ActivationGroup.currentGroupID(); 246 } 247 }