1 /*
   2  * Copyright (c) 1999, 2016, 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  * @author Laird Dornin
  28  *
  29  * @library ../../../testlibrary
  30  * @modules java.base/sun.security.provider
  31  *          java.rmi/sun.rmi.registry
  32  *          java.rmi/sun.rmi.server
  33  *          java.rmi/sun.rmi.transport
  34  *          java.rmi/sun.rmi.transport.tcp
  35  *          java.base/sun.nio.ch
  36  * @build TestLibrary RMID ActivationLibrary RMIDSelectorProvider
  37  *     CanCreateStubs StubClassesPermitted_Stub
  38  * @run main/othervm/java.security.policy=security.policy/secure=java.lang.SecurityManager/timeout=240 StubClassesPermitted
  39  */
  40 
  41 import java.io.ByteArrayOutputStream;
  42 import java.io.PrintStream;
  43 import java.rmi.MarshalledObject;
  44 import java.rmi.RemoteException;
  45 import java.rmi.activation.Activatable;
  46 import java.rmi.activation.ActivationDesc;
  47 import java.rmi.activation.ActivationGroup;
  48 import java.rmi.activation.ActivationGroupDesc;
  49 import java.rmi.activation.ActivationGroupDesc.CommandEnvironment;
  50 import java.rmi.activation.ActivationGroupID;
  51 import java.rmi.activation.ActivationID;
  52 import java.rmi.activation.ActivationSystem;
  53 import java.rmi.registry.Registry;
  54 import java.util.Properties;
  55 
  56 /**
  57  * The RMI activation system needs to explicitly allow itself to
  58  * create the following sun.* classes on behalf of code that runs with
  59  * user privileges and needs to make use of RMI activation:
  60  *
  61  *     sun.rmi.server.Activation$ActivationMonitorImpl_Stub
  62  *     sun.rmi.server.Activation$ActivationSystemImpl_Stub
  63  *     sun.rmi.registry.RegistryImpl_Stub
  64  *
  65  * The test causes the activation system to need to create each of
  66  * these classes in turn.  The test will fail if the activation system
  67  * does not allow these classes to be created.
  68  */
  69 public class StubClassesPermitted
  70     extends Activatable implements Runnable, CanCreateStubs
  71 {
  72     public static boolean sameGroup = false;
  73     private static int registryPort = -1;
  74     private static CanCreateStubs canCreateStubs = null;
  75     private static Registry registry = null;
  76 
  77     public static void main(String args[]) {
  78 
  79         sameGroup = true;
  80 
  81         RMID rmid = null;
  82 
  83         System.err.println("\nRegression test for bug/rfe 4179055\n");
  84 
  85         try {
  86             TestLibrary.suggestSecurityManager("java.lang.SecurityManager");
  87 
  88             registry = TestLibrary.createRegistryOnUnusedPort();
  89             registryPort = TestLibrary.getRegistryPort(registry);
  90 
  91             // must run with java.lang.SecurityManager or the test
  92             // result will be nullified if running with a build where
  93             // 4180392 has not been fixed.
  94             String smClassName =
  95                 System.getSecurityManager().getClass().getName();
  96             if (!smClassName.equals("java.lang.SecurityManager")) {
  97                 TestLibrary.bomb("Test must run with java.lang.SecurityManager");
  98             }
  99 
 100             // start an rmid.
 101             RMID.removeLog();
 102             rmid = RMID.createRMIDOnEphemeralPort();
 103             rmid.start();
 104 
 105             //rmid.addOptions(new String[] {"-C-Djava.rmi.server.logCalls=true"});
 106 
 107             // Ensure that activation groups run with the correct
 108             // security manager.
 109             //
 110             Properties p = new Properties();
 111             p.put("java.security.policy",
 112                   TestParams.defaultGroupPolicy);
 113             p.put("java.security.manager",
 114                   "java.lang.SecurityManager");
 115 
 116             // This action causes the following classes to be created
 117             // in this VM (RMI must permit the creation of these classes):
 118             //
 119             // sun.rmi.server.Activation$ActivationSystemImpl_Stub
 120             // sun.rmi.server.Activation$ActivationMonitorImpl_Stub
 121             //
 122             System.err.println("Create activation group, in a new VM");
 123             CommandEnvironment cmd = new ActivationGroupDesc.CommandEnvironment(null,
 124                     new String[] {
 125                         "--add-exports=java.base/sun.security.provider=ALL-UNNAMED",
 126                         "--add-exports=java.rmi/sun.rmi.registry=ALL-UNNAMED",
 127                         "--add-exports=java.rmi/sun.rmi.server=ALL-UNNAMED",
 128                         "--add-exports=java.rmi/sun.rmi.transport=ALL-UNNAMED",
 129                         "--add-exports=java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED" });
 130 
 131             ActivationGroupDesc groupDesc =
 132                 new ActivationGroupDesc(p, cmd);
 133             ActivationSystem system = ActivationGroup.getSystem();
 134             ActivationGroupID groupID = system.registerGroup(groupDesc);
 135 
 136             System.err.println("register activatable");
 137             // Fix for: 4271615: make sure activation group runs in a new VM
 138             ActivationDesc desc = new ActivationDesc
 139                 (groupID, "StubClassesPermitted", null, null);
 140             canCreateStubs = (CanCreateStubs) Activatable.register(desc);
 141 
 142             // ensure registry stub can be passed in a remote call
 143             System.err.println("getting the registry");
 144             registry = canCreateStubs.getRegistry();
 145 
 146             // make sure a client cant load just any sun.* class, just
 147             // as a sanity check, try to create a class we are not
 148             // allowed to access but which was passed in a remote call
 149             try {
 150                 System.err.println("accessing forbidden class");
 151                 Object secureRandom = canCreateStubs.getForbiddenClass();
 152 
 153                 TestLibrary.bomb("test allowed to access forbidden class," +
 154                                  " sun.security.provider.SecureRandom");
 155             } catch (java.security.AccessControlException e) {
 156 
 157                 // Make sure we received a *local* AccessControlException
 158                 ByteArrayOutputStream bout = new ByteArrayOutputStream();
 159                 PrintStream ps = new PrintStream(bout);
 160                 e.printStackTrace(ps);
 161                 ps.flush();
 162                 String trace = new String(bout.toByteArray());
 163                 if ((trace.indexOf("exceptionReceivedFromServer") >= 0) ||
 164                     trace.equals(""))
 165                 {
 166                     throw e;
 167                 }
 168                 System.err.println("received expected local access control exception");
 169             }
 170 
 171             // make sure that an ActivationGroupID can be passed in a
 172             // remote call; this is slightly more inclusive than
 173             // just passing a reference to the activation system
 174             System.err.println("returning group desc");
 175             canCreateStubs.returnGroupID();
 176 
 177             // Clean up object
 178             System.err.println
 179                 ("Deactivate object via method call");
 180             canCreateStubs.shutdown();
 181 
 182             System.err.println
 183                 ("\nsuccess: StubClassesPermitted test passed ");
 184 
 185         } catch (Exception e) {
 186             TestLibrary.bomb("\nfailure: unexpected exception ", e);
 187         } finally {
 188             try {
 189                 Thread.sleep(4000);
 190             } catch (InterruptedException e) {
 191             }
 192 
 193             canCreateStubs = null;
 194             rmid.cleanup();
 195             System.err.println("rmid shut down");
 196         }
 197     }
 198 
 199     static ActivationGroupID GroupID = null;
 200 
 201     /**
 202      * implementation of CanCreateStubs
 203      */
 204     public StubClassesPermitted
 205         (ActivationID id, MarshalledObject mo) throws RemoteException
 206     {
 207         // register/export anonymously
 208         super(id, 0);
 209 
 210         // obtain reference to the test registry
 211         registry = java.rmi.registry.LocateRegistry.
 212             getRegistry(registryPort);
 213     }
 214 
 215     /**
 216      * Spawns a thread to deactivate the object.
 217      */
 218     public void shutdown() throws Exception {
 219         (new Thread(this,"StubClassesPermitted")).start();
 220     }
 221 
 222     /**
 223      * Thread to deactivate object. First attempts to make object
 224      * inactive (via the inactive method).  If that fails (the
 225      * object may still have pending/executing calls), then
 226      * unexport the object forcibly.
 227      */
 228     public void run() {
 229         ActivationLibrary.deactivate(this, getID());
 230     }
 231 
 232     /**
 233      * Return a reference to the RMI registry, to make sure that
 234      * the stub for it can be deserialized in the test client VM.
 235      */
 236     public Registry getRegistry() throws RemoteException {
 237         if (sameGroup) {
 238             System.out.println("in same group");
 239         } else {
 240             System.out.println("not in same group");
 241         }
 242         return registry;
 243     }
 244 
 245     /**
 246      * Remote call to create and return a random serializable sun.*
 247      * class, the test should get a local security exception when
 248      * trying to create the class.  Ensure that not all sun.* classes
 249      * can be resolved in a remote call.
 250      */
 251     public Object getForbiddenClass() throws RemoteException {
 252         System.err.println("creating sun class");
 253         return new sun.security.provider.SecureRandom();
 254     }
 255 
 256     /**
 257      * Ensures that an activation group id can be passed in a remote
 258      * call (class may contain a remote reference to the activation
 259      * system implementation).
 260      */
 261     public ActivationGroupID returnGroupID() throws RemoteException {
 262         return ActivationGroup.currentGroupID();
 263     }
 264 }