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