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