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
41import java.io.ByteArrayOutputStream;
42import java.io.PrintStream;
43import java.rmi.MarshalledObject;
44import java.rmi.RemoteException;
45import java.rmi.activation.Activatable;
46import java.rmi.activation.ActivationDesc;
47import java.rmi.activation.ActivationGroup;
48import java.rmi.activation.ActivationGroupDesc;
49import java.rmi.activation.ActivationGroupDesc.CommandEnvironment;
50import java.rmi.activation.ActivationGroupID;
51import java.rmi.activation.ActivationID;
52import java.rmi.activation.ActivationSystem;
53import java.rmi.registry.Registry;
54import 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 */
69public 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.createRegistryOnEphemeralPort();
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}
265