|
1 /* |
|
2 * Copyright (c) 2014, 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 /* |
|
25 * @test |
|
26 * @bug 8047031 |
|
27 * @summary SocketPermission tests for legacy socket types |
|
28 * @library /test/lib |
|
29 * @build jdk.test.lib.NetworkConfiguration |
|
30 * jdk.test.lib.Platform |
|
31 * @run testng/othervm SocketPermissionTest |
|
32 */ |
|
33 |
|
34 import java.io.IOException; |
|
35 import java.net.DatagramPacket; |
|
36 import java.net.DatagramSocket; |
|
37 import java.net.InetAddress; |
|
38 import java.net.MulticastSocket; |
|
39 import java.net.NetworkInterface; |
|
40 import java.net.ServerSocket; |
|
41 import java.net.Socket; |
|
42 import java.net.SocketPermission; |
|
43 import java.security.AccessControlContext; |
|
44 import java.security.AccessController; |
|
45 import java.security.CodeSource; |
|
46 import java.security.Permission; |
|
47 import java.security.PermissionCollection; |
|
48 import java.security.Permissions; |
|
49 import java.security.Policy; |
|
50 import java.security.PrivilegedExceptionAction; |
|
51 import java.security.ProtectionDomain; |
|
52 import java.util.Optional; |
|
53 |
|
54 import org.testng.annotations.BeforeMethod; |
|
55 import org.testng.annotations.Test; |
|
56 |
|
57 import static org.testng.Assert.*; |
|
58 |
|
59 import static jdk.test.lib.NetworkConfiguration.probe; |
|
60 import static java.nio.charset.StandardCharsets.UTF_8; |
|
61 |
|
62 public class SocketPermissionTest { |
|
63 |
|
64 @BeforeMethod |
|
65 public void setupSecurityManager() throws Exception { |
|
66 // All permissions, a specific ACC will be used to when testing |
|
67 // with a reduced permission set. |
|
68 Policy.setPolicy(new Policy() { |
|
69 final PermissionCollection perms = new Permissions(); |
|
70 { perms.add(new java.security.AllPermission()); } |
|
71 public PermissionCollection getPermissions(ProtectionDomain domain) { |
|
72 return perms; |
|
73 } |
|
74 public PermissionCollection getPermissions(CodeSource codesource) { |
|
75 return perms; |
|
76 } |
|
77 public boolean implies(ProtectionDomain domain, Permission perm) { |
|
78 return perms.implies(perm); |
|
79 } |
|
80 } ); |
|
81 System.setSecurityManager(new SecurityManager()); |
|
82 } |
|
83 |
|
84 static final AccessControlContext RESTRICTED_ACC = getAccessControlContext(); |
|
85 |
|
86 @Test |
|
87 public void connectSocketTest() throws Exception { |
|
88 try (ServerSocket ss = new ServerSocket(0)) { |
|
89 int port = ss.getLocalPort(); |
|
90 |
|
91 String addr = "localhost:" + port; |
|
92 AccessControlContext acc = getAccessControlContext( |
|
93 new SocketPermission(addr, "listen,connect,resolve")); |
|
94 |
|
95 // Positive |
|
96 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
97 try (Socket client = new Socket(InetAddress.getLocalHost(), port)) { |
|
98 } |
|
99 return null; |
|
100 }, acc); |
|
101 |
|
102 //Negative |
|
103 try { |
|
104 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
105 Socket client = new Socket(InetAddress.getLocalHost(), port); |
|
106 fail("Expected SecurityException"); |
|
107 return null; |
|
108 }, RESTRICTED_ACC); |
|
109 } catch (SecurityException expected) { } |
|
110 } |
|
111 } |
|
112 |
|
113 @Test |
|
114 public void connectDatagramSocketTest() throws Exception { |
|
115 byte[] msg = "Hello".getBytes(UTF_8); |
|
116 InetAddress lh = InetAddress.getLocalHost(); |
|
117 |
|
118 try (DatagramSocket ds = new DatagramSocket(0)) { |
|
119 int port = ds.getLocalPort(); |
|
120 |
|
121 String addr = lh.getHostAddress() + ":" + port; |
|
122 AccessControlContext acc = getAccessControlContext( |
|
123 new SocketPermission(addr, "connect,resolve")); |
|
124 |
|
125 // Positive |
|
126 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
127 DatagramPacket dp = new DatagramPacket(msg, msg.length, lh, port); |
|
128 ds.send(dp); |
|
129 return null; |
|
130 }, acc); |
|
131 |
|
132 // Negative |
|
133 try { |
|
134 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
135 DatagramPacket dp = new DatagramPacket(msg, msg.length, lh, port); |
|
136 ds.send(dp); |
|
137 fail("Expected SecurityException"); |
|
138 return null; |
|
139 }, RESTRICTED_ACC); |
|
140 } catch (SecurityException expected) { } |
|
141 } |
|
142 } |
|
143 |
|
144 @Test |
|
145 public void acceptServerSocketTest() throws Exception { |
|
146 try (ServerSocket ss = new ServerSocket(0)) { |
|
147 int port = ss.getLocalPort(); |
|
148 |
|
149 String addr = "localhost:" + port; |
|
150 AccessControlContext acc = getAccessControlContext( |
|
151 new SocketPermission(addr, "listen,connect,resolve"), |
|
152 new SocketPermission("localhost:1024-", "accept")); |
|
153 |
|
154 // Positive |
|
155 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
156 InetAddress me = InetAddress.getLocalHost(); |
|
157 try (Socket client = new Socket(me, port)) { |
|
158 ss.accept(); |
|
159 } |
|
160 return null; |
|
161 }, acc); |
|
162 |
|
163 // Negative |
|
164 try { |
|
165 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
166 InetAddress me = InetAddress.getLocalHost(); |
|
167 try (Socket client = new Socket(me, port)) { |
|
168 ss.accept(); |
|
169 } |
|
170 fail("Expected SecurityException"); |
|
171 return null; |
|
172 }, RESTRICTED_ACC); |
|
173 } catch (SecurityException expected) { } |
|
174 } |
|
175 } |
|
176 |
|
177 @Test |
|
178 public void sendDatagramPacketTest() throws Exception { |
|
179 byte[] msg = "Hello".getBytes(UTF_8); |
|
180 InetAddress group = InetAddress.getByName("229.227.226.221"); |
|
181 |
|
182 try (DatagramSocket ds = new DatagramSocket(0)) { |
|
183 int port = ds.getLocalPort(); |
|
184 |
|
185 String addr = "localhost:" + port; |
|
186 //test for SocketPermission "229.227.226.221", "connect,accept" |
|
187 AccessControlContext acc = getAccessControlContext( |
|
188 new SocketPermission(addr, "listen,resolve"), |
|
189 new SocketPermission("229.227.226.221", "connect,accept")); |
|
190 |
|
191 // Positive |
|
192 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
193 DatagramPacket hi = new DatagramPacket(msg, msg.length, group, port); |
|
194 ds.send(hi); |
|
195 return null; |
|
196 }, acc); |
|
197 |
|
198 // Negative |
|
199 try { |
|
200 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
201 DatagramPacket hi = new DatagramPacket(msg, msg.length, group, port); |
|
202 ds.send(hi); |
|
203 fail("Expected SecurityException"); |
|
204 return null; |
|
205 }, RESTRICTED_ACC); |
|
206 } catch (SecurityException expected) { } |
|
207 } |
|
208 } |
|
209 |
|
210 @Test |
|
211 public void joinGroupMulticastTest() throws Exception { |
|
212 InetAddress group = InetAddress.getByName("229.227.226.221"); |
|
213 try (MulticastSocket s = new MulticastSocket(0)) { |
|
214 int port = s.getLocalPort(); |
|
215 |
|
216 String addr = "localhost:" + port; |
|
217 AccessControlContext acc = getAccessControlContext( |
|
218 new SocketPermission(addr, "listen,resolve"), |
|
219 new SocketPermission("229.227.226.221", "connect,accept")); |
|
220 |
|
221 // Positive ( requires a functional network interface ) |
|
222 Optional<NetworkInterface> onif = probe().ip4MulticastInterfaces().findFirst(); |
|
223 if (!onif.isPresent()) { |
|
224 s.setNetworkInterface(onif.get()); |
|
225 |
|
226 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
227 s.joinGroup(group); |
|
228 s.leaveGroup(group); |
|
229 return null; |
|
230 }, acc); |
|
231 } |
|
232 |
|
233 // Negative |
|
234 try { |
|
235 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
236 s.joinGroup(group); |
|
237 s.leaveGroup(group); |
|
238 fail("Expected SecurityException"); |
|
239 return null; |
|
240 }, RESTRICTED_ACC); |
|
241 } catch (SecurityException expected) { } |
|
242 } |
|
243 |
|
244 } |
|
245 |
|
246 @Test |
|
247 public void listenDatagramSocketTest() throws Exception { |
|
248 // the hardcoded port number doesn't really matter since we expect the |
|
249 // security permission to be checked before the underlying operation. |
|
250 int port = 8899; |
|
251 String addr = "localhost:" + port; |
|
252 AccessControlContext acc = getAccessControlContext( |
|
253 new SocketPermission(addr, "listen")); |
|
254 |
|
255 // Positive |
|
256 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
257 try (DatagramSocket ds = new DatagramSocket(port)) { } |
|
258 catch (IOException intermittentlyExpected) { /* ignore */ } |
|
259 return null; |
|
260 }, acc); |
|
261 |
|
262 // Negative |
|
263 try { |
|
264 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
265 try (DatagramSocket ds = new DatagramSocket(port)) { } |
|
266 catch (IOException intermittentlyExpected) { /* ignore */ } |
|
267 fail("Expected SecurityException"); |
|
268 return null; |
|
269 }, RESTRICTED_ACC); |
|
270 } catch (SecurityException expected) { } |
|
271 } |
|
272 |
|
273 @Test |
|
274 public void listenMulticastSocketTest() throws Exception { |
|
275 // the hardcoded port number doesn't really matter since we expect the |
|
276 // security permission to be checked before the underlying operation. |
|
277 int port = 8899; |
|
278 String addr = "localhost:" + port; |
|
279 AccessControlContext acc = getAccessControlContext( |
|
280 new SocketPermission(addr, "listen")); |
|
281 |
|
282 // Positive |
|
283 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
284 try (MulticastSocket ms = new MulticastSocket(port)) { } |
|
285 catch (IOException intermittentlyExpected) { /* ignore */ } |
|
286 return null; |
|
287 }, acc); |
|
288 |
|
289 // Negative |
|
290 try { |
|
291 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
292 try (MulticastSocket ms = new MulticastSocket(port)) { } |
|
293 catch (IOException intermittentlyExpected) { /* ignore */ } |
|
294 fail("Expected SecurityException"); |
|
295 return null; |
|
296 }, RESTRICTED_ACC); |
|
297 } catch (SecurityException expected) { } |
|
298 } |
|
299 |
|
300 @Test |
|
301 public void listenServerSocketTest() throws Exception { |
|
302 // the hardcoded port number doesn't really matter since we expect the |
|
303 // security permission to be checked before the underlying operation. |
|
304 int port = 8899; |
|
305 String addr = "localhost:" + port; |
|
306 AccessControlContext acc = getAccessControlContext( |
|
307 new SocketPermission(addr, "listen")); |
|
308 |
|
309 // Positive |
|
310 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
311 try (ServerSocket ss = new ServerSocket(port)) { } |
|
312 catch (IOException intermittentlyExpected) { /* ignore */ } |
|
313 return null; |
|
314 }, acc); |
|
315 |
|
316 // Negative |
|
317 try { |
|
318 AccessController.doPrivileged((PrivilegedExceptionAction<Void>) () -> { |
|
319 try (ServerSocket ss = new ServerSocket(port)) { } |
|
320 catch (IOException intermittentlyExpected) { /* ignore */ } |
|
321 fail("Expected SecurityException"); |
|
322 return null; |
|
323 }, RESTRICTED_ACC); |
|
324 } catch (SecurityException expected) { } |
|
325 |
|
326 } |
|
327 |
|
328 private static AccessControlContext getAccessControlContext(Permission... ps) { |
|
329 Permissions perms = new Permissions(); |
|
330 for (Permission p : ps) { |
|
331 perms.add(p); |
|
332 } |
|
333 /* |
|
334 *Create an AccessControlContext that consist a single protection domain |
|
335 * with only the permissions calculated above |
|
336 */ |
|
337 ProtectionDomain pd = new ProtectionDomain(null, perms); |
|
338 return new AccessControlContext(new ProtectionDomain[]{pd}); |
|
339 } |
|
340 |
|
341 // Standalone entry point for running with, possibly older, JDKs. |
|
342 public static void main(String[] args) throws Throwable { |
|
343 SocketPermissionTest test = new SocketPermissionTest(); |
|
344 test.setupSecurityManager(); |
|
345 for (java.lang.reflect.Method m : SocketPermissionTest.class.getDeclaredMethods()) { |
|
346 if (m.getAnnotation(Test.class) != null) { |
|
347 System.out.println("Invoking " + m.getName()); |
|
348 m.invoke(test); |
|
349 } |
|
350 } |
|
351 } |
|
352 } |