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 java.io.File;
20import java.io.FileOutputStream;
21import java.io.IOException;
22import java.io.ObjectOutputStream;
23import java.io.OutputStream;
24import java.io.SerializablePermission;
25import java.io.StreamCorruptedException;
26import java.security.Permission;
27
28import junit.framework.TestCase;
29import dalvik.annotation.TestLevel;
30import dalvik.annotation.TestTargetClass;
31import dalvik.annotation.TestTargetNew;
32
33/*
34 * This class tests the security permissions which are documented in
35 * http://java.sun.com/j2se/1.5.0/docs/guide/security/permissions.html#PermsAndMethods
36 * for class java.io.ObjectOutputStream
37 */
38@TestTargetClass(java.io.ObjectOutputStream.class)
39public class JavaIoObjectOutputStreamTest extends TestCase {
40
41    SecurityManager old;
42
43    @Override
44    protected void setUp() throws Exception {
45        old = System.getSecurityManager();
46        super.setUp();
47    }
48
49    @Override
50    protected void tearDown() throws Exception {
51        System.setSecurityManager(old);
52        super.tearDown();
53    }
54    @TestTargetNew(
55        level = TestLevel.PARTIAL_COMPLETE,
56        notes = "Verifies that enableReplaceObject(boolean) method calls " +
57                "checkPermission on security manager.",
58        method = "enableReplaceObject",
59        args = {boolean.class}
60    )
61    public void test_ObjectOutputStream() throws IOException {
62        class TestSecurityManager extends SecurityManager {
63            boolean called;
64            Permission permission;
65            void reset(){
66                called = false;
67                permission = null;
68            }
69            @Override
70            public void checkPermission(Permission permission){
71                if(permission instanceof SerializablePermission){
72                    called = true;
73                    this.permission = permission;
74                }
75            }
76        }
77
78        // TestObjectOutputStream is necessary in order to call enableReplaceObject
79        class TestObjectOutputStream extends ObjectOutputStream  {
80            TestObjectOutputStream(OutputStream s) throws StreamCorruptedException, IOException {
81                super(s);
82            }
83            @Override
84            public boolean enableReplaceObject(boolean enable) throws SecurityException {
85                return super.enableReplaceObject(enable);
86            }
87        }
88
89        long id = new java.util.Date().getTime();
90        String filename  = "SecurityPermissionsTest_"+id;
91        File f = File.createTempFile(filename, null);
92        f.deleteOnExit();
93
94        TestObjectOutputStream ois = new TestObjectOutputStream(new FileOutputStream(f));
95
96        TestSecurityManager s = new TestSecurityManager();
97        System.setSecurityManager(s);
98
99        s.reset();
100        ois.enableReplaceObject(true);
101        assertTrue("ObjectOutputStream.enableReplaceObject(boolean) must call checkPermission on security manager", s.called);
102        assertEquals("Name of SerializablePermission is not correct", "enableSubstitution", s.permission.getName());
103    }
104
105    @TestTargetNew(
106        level = TestLevel.PARTIAL_COMPLETE,
107        notes = "Verifies that ObjectOutputStream constructor calls " +
108                "checkPermission on security manager.",
109        method = "ObjectOutputStream",
110        args = {}
111    )
112    public void test_ObjecOutputStream2() throws IOException {
113        class TestSecurityManager extends SecurityManager {
114            boolean called;
115            Permission permission;
116            void reset(){
117                called = false;
118                permission = null;
119            }
120            @Override
121            public void checkPermission(Permission permission){
122                if(permission instanceof SerializablePermission){
123                    called = true;
124                    this.permission = permission;
125                }
126            }
127        }
128
129        // Beginning with J2SE 1.4.0, ObjectOutputStream's public one-argument constructor
130        // requires the "enableSubclassImplementation" SerializablePermission when invoked
131        // (either directly or indirectly) by a subclass which overrides
132        // ObjectOutputStream.putFields or ObjectOutputStream.writeUnshared.
133
134        class TestObjectOutputStream extends ObjectOutputStream  {
135            TestObjectOutputStream(OutputStream s) throws StreamCorruptedException, IOException {
136                super(s);
137            }
138        }
139
140        class TestObjectOutputStream_putFields extends ObjectOutputStream  {
141            TestObjectOutputStream_putFields(OutputStream s) throws StreamCorruptedException, IOException {
142                super(s);
143            }
144            @Override
145            public PutField putFields() throws IOException {
146                return super.putFields();
147            }
148        }
149
150        class TestObjectOutputStream_writeUnshared extends ObjectOutputStream  {
151            TestObjectOutputStream_writeUnshared(OutputStream s) throws StreamCorruptedException, IOException {
152                super(s);
153            }
154            @Override
155            public void writeUnshared(Object object) throws IOException {
156                super.writeUnshared(object);
157            }
158
159        }
160
161        long id = new java.util.Date().getTime();
162        String filename  = "SecurityPermissionsTest_"+id;
163        File f = File.createTempFile(filename, null);
164        f.deleteOnExit();
165
166        TestSecurityManager s = new TestSecurityManager();
167        System.setSecurityManager(s);
168
169        s.reset();
170        new ObjectOutputStream(new FileOutputStream(f));
171        assertTrue("ObjectOutputStream(OutputStream) ctor must not call checkPermission on security manager on a class which neither overwrites writeUnshared nor putFields", !s.called);
172
173        s.reset();
174        new TestObjectOutputStream(new FileOutputStream(f));
175        assertTrue("ObjectOutputStream(OutputStream) ctor must not call checkPermission on security manager on a class which neither overwrites writeUnshared nor putFields", !s.called);
176
177        s.reset();
178        new TestObjectOutputStream_writeUnshared(new FileOutputStream(f));
179        assertTrue("ObjectOutputStream(OutputStream) ctor must call checkPermission on security manager on a class which overwrites method writeUnshared", s.called);
180        assertEquals("Name of SerializablePermission is not correct", "enableSubclassImplementation", s.permission.getName());
181
182        s.reset();
183        new TestObjectOutputStream_putFields(new FileOutputStream(f));
184        assertTrue("ObjectOutputStream(OutputStream) ctor must call checkPermission on security manager on a class which overwrites method putFields", s.called);
185        assertEquals("Name of SerializablePermission is not correct", "enableSubclassImplementation", s.permission.getName());
186
187    }
188
189}
190