1/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package tests.security.permissions;
18
19import dalvik.annotation.TestTargets;
20import dalvik.annotation.TestLevel;
21import dalvik.annotation.TestTargetNew;
22import dalvik.annotation.TestTargetClass;
23
24import junit.framework.TestCase;
25
26import java.io.IOException;
27import java.security.Permission;
28/*
29 * This class tests the security permissions which are documented in
30 * http://java.sun.com/j2se/1.5.0/docs/guide/security/permissions.html#PermsAndMethods
31 * for class java.lang.Runtime
32 */
33@TestTargetClass(java.lang.Runtime.class)
34public class JavaLangRuntimeTest extends TestCase {
35
36    SecurityManager old;
37
38    @Override
39    protected void setUp() throws Exception {
40        old = System.getSecurityManager();
41        super.setUp();
42    }
43
44    @Override
45    protected void tearDown() throws Exception {
46        System.setSecurityManager(old);
47        super.tearDown();
48    }
49
50    @TestTargets({
51        @TestTargetNew(
52            level = TestLevel.PARTIAL,
53            notes = "Verifies that Runtime.exec calls checkExec method on security manager",
54            method = "exec",
55            args = {java.lang.String.class}
56        ),
57        @TestTargetNew(
58            level = TestLevel.PARTIAL,
59            notes = "Verifies that Runtime.exec calls checkExec method on security manager",
60            method = "exec",
61            args = {java.lang.String.class, java.lang.String[].class}
62        ),
63        @TestTargetNew(
64            level = TestLevel.PARTIAL,
65            notes = "Verifies that Runtime.exec calls checkExec method on security manager",
66            method = "exec",
67            args = {java.lang.String[].class}
68        ),
69        @TestTargetNew(
70            level = TestLevel.PARTIAL,
71            notes = "Verifies that Runtime.exec calls checkExec method on security manager",
72            method = "exec",
73            args = {java.lang.String[].class, java.lang.String[].class}
74        )
75    })
76    public void test_exec() throws IOException {
77        class TestSecurityManager extends SecurityManager {
78            boolean called;
79            String cmd;
80            void reset(){
81                called = false;
82                cmd = null;
83            }
84            @Override
85            public void checkExec(String cmd) {
86                called = true;
87                this.cmd = cmd;
88            }
89            @Override
90            public void checkPermission(Permission p) {
91
92            }
93        }
94
95        String cmd = "ls";
96        String arg = "-al";
97
98        TestSecurityManager s = new TestSecurityManager();
99        System.setSecurityManager(s);
100
101        s.reset();
102        Runtime.getRuntime().exec(cmd);
103        assertTrue("Runtime.exec must call checkExcec on security manager", s.called);
104        assertEquals("Argument of checkExec is not correct", cmd, s.cmd);
105
106        s.reset();
107        Runtime.getRuntime().exec(cmd, null);
108        assertTrue("Runtime.exec must call checkExcec on security manager", s.called);
109        assertEquals("Argument of checkExec is not correct", cmd, s.cmd);
110
111        s.reset();
112        Runtime.getRuntime().exec(new String[]{cmd, arg});
113        assertTrue("Runtime.exec must call checkExcec on security manager", s.called);
114        assertEquals("Argument of checkExec is not correct", cmd, s.cmd);
115
116        s.reset();
117        Runtime.getRuntime().exec(new String[]{cmd, arg}, null);
118        assertTrue("Runtime.exec must call checkExcec on security manager", s.called);
119        assertEquals("Argument of checkExec is not correct", cmd, s.cmd);
120    }
121
122    @TestTargets({
123        @TestTargetNew(
124            level = TestLevel.PARTIAL,
125            notes = "Verifies that addShutdownHook and remove ShutdownHook call checkPermission on security manager., disabled due to implementation bug, see ticket #55",
126            method = "addShutdownHook",
127            args = {java.lang.Thread.class}
128        ),
129        @TestTargetNew(
130            level = TestLevel.PARTIAL,
131            notes = "Verifies that addShutdownHook and remove ShutdownHook call checkPermission on security manager., disabled due to implementation bug, see ticket #55",
132            method = "removeShutdownHook",
133            args = {java.lang.Thread.class}
134        )
135    })
136    public void test_shutdownHook() {
137        class TestSecurityManager extends SecurityManager {
138            boolean called;
139            Permission permission;
140            void reset(){
141                called = false;
142                permission = null;
143            }
144            @Override
145            public void checkPermission(Permission permission){
146                if(permission instanceof RuntimePermission){
147                    called = true;
148                    this.permission = permission;
149                }
150            }
151        }
152
153        Thread hook = new Thread(){};
154
155        TestSecurityManager s = new TestSecurityManager();
156        System.setSecurityManager(s);
157
158        s.reset();
159        Runtime.getRuntime().addShutdownHook(hook);
160        assertTrue("Runtime.addShutdownHook must call checkPermission on security manager with a RuntimePermission", s.called);
161        assertEquals("Name of RuntimePermission passed to checkPermission is not correct", "shutdownHooks", s.permission.getName());
162
163        s.reset();
164        Runtime.getRuntime().removeShutdownHook(hook);
165        assertTrue("Runtime.removeShutdownHook must call checkPermission on security manager with a RuntimePermission", s.called);
166        assertEquals("Name of RuntimePermission passed to checkPermission is not correct", "shutdownHooks", s.permission.getName());
167    }
168
169    @TestTargetNew(
170        level = TestLevel.PARTIAL,
171        notes = "Verifies that exit calls checkExit on security manager.",
172        method = "exit",
173        args = {int.class}
174    )
175    public void test_exit() {
176        class ExitNotAllowedException extends RuntimeException {}
177        class TestSecurityManager extends SecurityManager {
178            boolean called;
179            int status;
180            void reset(){
181                called = false;
182                status = -1;
183            }
184            @Override
185            public void checkExit(int status){
186                this.called = true;
187                this.status = status;
188                throw new ExitNotAllowedException(); // prevent that the system is shut down
189            }
190            @Override
191            public void checkPermission(Permission p) {
192
193            }
194        }
195
196        TestSecurityManager s = new TestSecurityManager();
197        System.setSecurityManager(s);
198
199        s.reset();
200        try {
201            Runtime.getRuntime().exit(11);
202            fail("Runtime.exit must call checkExit on security manager with a RuntimePermission");
203        }
204        catch(ExitNotAllowedException e){
205             // expected exception
206        }
207        assertTrue("Runtime.exit must call checkExit on security manager with a RuntimePermission", s.called);
208        assertEquals("Argument of checkExit is not correct", 11, s.status);
209    }
210
211    @TestTargetNew(
212        level = TestLevel.PARTIAL,
213        notes = "Verifies that runFinalizersOnExit calls checkExit on security manager., disabled due to implementation bug, see ticket #55",
214        method = "runFinalizersOnExit",
215        args = {boolean.class}
216    )
217    public void test_runFinalizersOnExit() {
218        class TestSecurityManager extends SecurityManager {
219            boolean called;
220            int status;
221            void reset(){
222                called = false;
223                status = -1;
224            }
225            @Override
226            public void checkExit(int status){
227                this.called = true;
228                this.status = status;
229            }
230            @Override
231            public void checkPermission(Permission p) {
232
233            }
234        }
235
236        TestSecurityManager s = new TestSecurityManager();
237        System.setSecurityManager(s);
238
239        s.reset();
240        Runtime.runFinalizersOnExit(true);
241        assertTrue("Runtime.runFinalizersOnExit must call checkExit on security manager with a RuntimePermission", s.called);
242        assertEquals("Argument of checkExit is not correct", 0, s.status);
243
244        s.reset();
245        Runtime.runFinalizersOnExit(false);
246        assertTrue("Runtime.runFinalizersOnExit must call checkExit on security manager with a RuntimePermission", s.called);
247        assertEquals("Argument of checkExit is not correct", 0, s.status);
248    }
249
250    @TestTargets({
251        @TestTargetNew(
252            level = TestLevel.PARTIAL,
253            notes = "Verifies that methods load and loadLibrary call checkLink on security manager.",
254            method = "load",
255            args = {java.lang.String.class}
256        ),
257        @TestTargetNew(
258            level = TestLevel.PARTIAL,
259            notes = "Verifies that methods load and loadLibrary call checkLink on security manager.",
260            method = "loadLibrary",
261            args = {java.lang.String.class}
262        )
263    })
264    public void test_load() {
265        final String library = "library";
266
267        class CheckLinkCalledException extends RuntimeException {}
268
269        class TestSecurityManager extends SecurityManager {
270            @Override
271            public void checkLink(String lib){
272                if(library.equals(lib)){
273                    throw new CheckLinkCalledException();
274                }
275            }
276            @Override
277            public void checkPermission(Permission p) {
278
279            }
280        }
281
282        TestSecurityManager s = new TestSecurityManager();
283        System.setSecurityManager(s);
284
285        try {
286            Runtime.getRuntime().load(library);
287            fail("System.load must call checkLink on security manager with argument "+library);
288        }
289        catch(CheckLinkCalledException e){
290            // ok
291        }
292        catch(Throwable t){
293            fail("System.load must call checkLink on security manager with argument "+library);
294        }
295
296        try {
297            Runtime.getRuntime().loadLibrary(library);
298            fail("System.load must call checkLink on security manager with argument "+library);
299        }
300        catch(CheckLinkCalledException e){
301            // ok
302        }
303        catch(Throwable t){
304            fail("System.load must call checkLink on security manager with argument "+library);
305        }
306    }
307
308}
309