1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.logging.security;
19
20 import static org.junit.Assert.assertNotEquals;
21
22 import java.io.PrintWriter;
23 import java.io.StringWriter;
24 import java.lang.reflect.Field;
25 import java.lang.reflect.InvocationTargetException;
26 import java.lang.reflect.Method;
27 import java.util.Hashtable;
28
29 import junit.framework.Test;
30 import junit.framework.TestCase;
31
32 import org.apache.commons.lang3.JavaVersion;
33 import org.apache.commons.lang3.SystemUtils;
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.commons.logging.PathableClassLoader;
37 import org.apache.commons.logging.PathableTestSuite;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 public class SecurityForbiddenTestCase extends TestCase {
58
59
60
61
62 public static class CustomHashtable extends Hashtable<Object, Object> {
63
64
65
66
67 private static final long serialVersionUID = 7224652794746236024L;
68 }
69
70
71
72
73 public static Test suite() throws Exception {
74 final PathableClassLoader parent = new PathableClassLoader(null);
75 parent.useExplicitLoader("junit.", Test.class.getClassLoader());
76 parent.useExplicitLoader("org.junit.", Test.class.getClassLoader());
77 parent.addLogicalLib("commons-logging");
78 parent.addLogicalLib("testclasses");
79 parent.addLogicalLib("commons-lang3");
80
81 final Class<?> testClass = parent.loadClass("org.apache.commons.logging.security.SecurityForbiddenTestCase");
82 return new PathableTestSuite(testClass, parent);
83 }
84
85 private SecurityManager oldSecMgr;
86
87 private ClassLoader otherClassLoader;
88
89
90
91
92 private Object loadClass(final String name, final ClassLoader classLoader) {
93 try {
94 final Class<?> clazz = classLoader.loadClass(name);
95 return clazz.getConstructor().newInstance();
96 } catch (final Exception e) {
97 final Throwable wrapped = e instanceof InvocationTargetException ? ((InvocationTargetException) e).getTargetException() : e;
98 final StringWriter sw = new StringWriter();
99 final PrintWriter pw = new PrintWriter(sw);
100 wrapped.printStackTrace(pw);
101 fail("Unexpected exception:" + wrapped.getMessage() + ":" + sw);
102 }
103 return null;
104 }
105
106 @Override
107 public void setUp() {
108
109 oldSecMgr = System.getSecurityManager();
110
111 final PathableClassLoader classLoader = new PathableClassLoader(null);
112 classLoader.addLogicalLib("commons-logging");
113 classLoader.addLogicalLib("testclasses");
114
115 otherClassLoader = classLoader;
116 }
117
118 @Override
119 public void tearDown() {
120
121
122 if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_21)) {
123 return;
124 }
125
126
127
128 System.setSecurityManager(oldSecMgr);
129 }
130
131
132
133
134
135
136 public void testAllForbidden() {
137
138
139 if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_21)) {
140 return;
141 }
142 System.setProperty(
143 LogFactory.HASHTABLE_IMPLEMENTATION_PROPERTY,
144 CustomHashtable.class.getName());
145 final MockSecurityManager mySecurityManager = new MockSecurityManager();
146
147 System.setSecurityManager(mySecurityManager);
148
149 try {
150
151
152 final Class<?> c = this.getClass().getClassLoader().loadClass(
153 "org.apache.commons.logging.LogFactory");
154 final Method m = c.getMethod("getLog", Class.class);
155 final Log log = (Log) m.invoke(null, this.getClass());
156 log.info("testing");
157
158
159
160
161
162
163
164 System.setSecurityManager(oldSecMgr);
165 final Field factoryField = c.getDeclaredField("factories");
166 factoryField.setAccessible(true);
167 final Object factoryTable = factoryField.get(null);
168 assertNotNull(factoryTable);
169 final String ftClassName = factoryTable.getClass().getName();
170 assertNotEquals("Custom Hashtable unexpectedly used",
171 CustomHashtable.class.getName(), ftClassName);
172
173 assertEquals(0, mySecurityManager.getUntrustedCodeCount());
174 } catch (final Throwable t) {
175
176
177
178
179 System.setSecurityManager(oldSecMgr);
180 final StringWriter sw = new StringWriter();
181 final PrintWriter pw = new PrintWriter(sw);
182 t.printStackTrace(pw);
183 fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString());
184 }
185 }
186
187
188
189
190
191
192 public void testContextClassLoader() {
193
194
195 if (SystemUtils.isJavaVersionAtLeast(JavaVersion.JAVA_21)) {
196 return;
197 }
198 System.setProperty(
199 LogFactory.HASHTABLE_IMPLEMENTATION_PROPERTY,
200 CustomHashtable.class.getName());
201 final MockSecurityManager mySecurityManager = new MockSecurityManager();
202
203 System.setSecurityManager(mySecurityManager);
204
205 try {
206
207
208
209 loadClass("org.apache.commons.logging.security.DummyClass", otherClassLoader);
210
211 System.setSecurityManager(oldSecMgr);
212 assertEquals(0, mySecurityManager.getUntrustedCodeCount());
213 } catch (final Throwable t) {
214
215
216
217 System.setSecurityManager(oldSecMgr);
218 final StringWriter sw = new StringWriter();
219 final PrintWriter pw = new PrintWriter(sw);
220 t.printStackTrace(pw);
221 fail("Unexpected exception:" + t.getMessage() + ":" + sw.toString());
222 }
223 }
224 }