/* * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ /* * @test * @bug 8047031 * @summary SocketPermission tests for legacy socket types * @run testng/othervm SocketPermissionTest */ import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.MulticastSocket; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketPermission; import java.security.AccessControlContext; import java.security.AccessController; import java.security.CodeSource; import java.security.Permission; import java.security.PermissionCollection; import java.security.Permissions; import java.security.Policy; import java.security.PrivilegedExceptionAction; import java.security.ProtectionDomain; import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import static org.testng.Assert.*; import static java.nio.charset.StandardCharsets.UTF_8; public class SocketPermissionTest { @BeforeMethod public void setupSecurityManager() throws Exception { // All permissions, a specific ACC will be used to when testing // with a reduced permission set. Policy.setPolicy(new Policy() { final PermissionCollection perms = new Permissions(); { perms.add(new java.security.AllPermission()); } public PermissionCollection getPermissions(ProtectionDomain domain) { return perms; } public PermissionCollection getPermissions(CodeSource codesource) { return perms; } public boolean implies(ProtectionDomain domain, Permission perm) { return perms.implies(perm); } } ); System.setSecurityManager(new SecurityManager()); } static final AccessControlContext RESTRICTED_ACC = getAccessControlContext(); @Test public void connectSocketTest() throws Exception { try (ServerSocket ss = new ServerSocket(0)) { int port = ss.getLocalPort(); String addr = "localhost:" + port; AccessControlContext acc = getAccessControlContext( new SocketPermission(addr, "listen,connect,resolve")); // Positive AccessController.doPrivileged((PrivilegedExceptionAction) () -> { try (Socket client = new Socket(InetAddress.getLocalHost(), port)) { } return null; }, acc); //Negative try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { Socket client = new Socket(InetAddress.getLocalHost(), port); fail("Expected SecurityException"); return null; }, RESTRICTED_ACC); } catch (SecurityException expected) { } } } @Test public void connectDatagramSocketTest() throws Exception { byte[] msg = "Hello".getBytes(UTF_8); InetAddress lh = InetAddress.getLocalHost(); try (DatagramSocket ds = new DatagramSocket(0)) { int port = ds.getLocalPort(); String addr = lh.getHostAddress() + ":" + port; AccessControlContext acc = getAccessControlContext( new SocketPermission(addr, "connect,resolve")); // Positive AccessController.doPrivileged((PrivilegedExceptionAction) () -> { DatagramPacket dp = new DatagramPacket(msg, msg.length, lh, port); ds.send(dp); return null; }, acc); // Negative try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { DatagramPacket dp = new DatagramPacket(msg, msg.length, lh, port); ds.send(dp); fail("Expected SecurityException"); return null; }, RESTRICTED_ACC); } catch (SecurityException expected) { } } } @Test public void acceptServerSocketTest() throws Exception { try (ServerSocket ss = new ServerSocket(0)) { int port = ss.getLocalPort(); String addr = "localhost:" + port; AccessControlContext acc = getAccessControlContext( new SocketPermission(addr, "listen,connect,resolve"), new SocketPermission("localhost:1024-", "accept")); // Positive AccessController.doPrivileged((PrivilegedExceptionAction) () -> { InetAddress me = InetAddress.getLocalHost(); try (Socket client = new Socket(me, port)) { ss.accept(); } return null; }, acc); // Negative try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { InetAddress me = InetAddress.getLocalHost(); try (Socket client = new Socket(me, port)) { ss.accept(); } fail("Expected SecurityException"); return null; }, RESTRICTED_ACC); } catch (SecurityException expected) { } } } @Test public void sendDatagramPacketTest() throws Exception { byte[] msg = "Hello".getBytes(UTF_8); InetAddress group = InetAddress.getByName("229.227.226.221"); try (DatagramSocket ds = new DatagramSocket(0)) { int port = ds.getLocalPort(); String addr = "localhost:" + port; //test for SocketPermission "229.227.226.221", "connect,accept" AccessControlContext acc = getAccessControlContext( new SocketPermission(addr, "listen,resolve"), new SocketPermission("229.227.226.221", "connect,accept")); // Positive AccessController.doPrivileged((PrivilegedExceptionAction) () -> { DatagramPacket hi = new DatagramPacket(msg, msg.length, group, port); ds.send(hi); return null; }, acc); // Negative try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { DatagramPacket hi = new DatagramPacket(msg, msg.length, group, port); ds.send(hi); fail("Expected SecurityException"); return null; }, RESTRICTED_ACC); } catch (SecurityException expected) { } } } @Test public void joinGroupMulticastTest() throws Exception { InetAddress group = InetAddress.getByName("229.227.226.221"); try (MulticastSocket s = new MulticastSocket(0)) { int port = s.getLocalPort(); String addr = "localhost:" + port; AccessControlContext acc = getAccessControlContext( new SocketPermission(addr, "listen,resolve"), new SocketPermission("229.227.226.221", "connect,accept")); // Positive AccessController.doPrivileged((PrivilegedExceptionAction) () -> { s.joinGroup(group); s.leaveGroup(group); return null; }, acc); // Negative try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { s.joinGroup(group); s.leaveGroup(group); fail("Expected SecurityException"); return null; }, RESTRICTED_ACC); } catch (SecurityException expected) { } } } @Test public void listenDatagramSocketTest() throws Exception { // the hardcoded port number doesn't really matter since we expect the // security permission to be checked before the underlying operation. int port = 8899; String addr = "localhost:" + port; AccessControlContext acc = getAccessControlContext( new SocketPermission(addr, "listen")); // Positive AccessController.doPrivileged((PrivilegedExceptionAction) () -> { try (DatagramSocket ds = new DatagramSocket(port)) { } catch (IOException intermittentlyExpected) { /* ignore */ } return null; }, acc); // Negative try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { try (DatagramSocket ds = new DatagramSocket(port)) { } catch (IOException intermittentlyExpected) { /* ignore */ } fail("Expected SecurityException"); return null; }, RESTRICTED_ACC); } catch (SecurityException expected) { } } @Test public void listenMulticastSocketTest() throws Exception { // the hardcoded port number doesn't really matter since we expect the // security permission to be checked before the underlying operation. int port = 8899; String addr = "localhost:" + port; AccessControlContext acc = getAccessControlContext( new SocketPermission(addr, "listen")); // Positive AccessController.doPrivileged((PrivilegedExceptionAction) () -> { try (MulticastSocket ms = new MulticastSocket(port)) { } catch (IOException intermittentlyExpected) { /* ignore */ } return null; }, acc); // Negative try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { try (MulticastSocket ms = new MulticastSocket(port)) { } catch (IOException intermittentlyExpected) { /* ignore */ } fail("Expected SecurityException"); return null; }, RESTRICTED_ACC); } catch (SecurityException expected) { } } @Test public void listenServerSocketTest() throws Exception { // the hardcoded port number doesn't really matter since we expect the // security permission to be checked before the underlying operation. int port = 8899; String addr = "localhost:" + port; AccessControlContext acc = getAccessControlContext( new SocketPermission(addr, "listen")); // Positive AccessController.doPrivileged((PrivilegedExceptionAction) () -> { try (ServerSocket ss = new ServerSocket(port)) { } catch (IOException intermittentlyExpected) { /* ignore */ } return null; }, acc); // Negative try { AccessController.doPrivileged((PrivilegedExceptionAction) () -> { try (ServerSocket ss = new ServerSocket(port)) { } catch (IOException intermittentlyExpected) { /* ignore */ } fail("Expected SecurityException"); return null; }, RESTRICTED_ACC); } catch (SecurityException expected) { } } private static AccessControlContext getAccessControlContext(Permission... ps) { Permissions perms = new Permissions(); for (Permission p : ps) { perms.add(p); } /* *Create an AccessControlContext that consist a single protection domain * with only the permissions calculated above */ ProtectionDomain pd = new ProtectionDomain(null, perms); return new AccessControlContext(new ProtectionDomain[]{pd}); } // Standalone entry point for running with, possibly older, JDKs. public static void main(String[] args) throws Throwable { SocketPermissionTest test = new SocketPermissionTest(); test.setupSecurityManager(); for (java.lang.reflect.Method m : SocketPermissionTest.class.getDeclaredMethods()) { if (m.getAnnotation(Test.class) != null) { System.out.println("Invoking " + m.getName()); m.invoke(test); } } } }