1 /*
   2  * Copyright (c) 2014, 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 ../../../lib/testlibrary
  29  * @run testng/othervm/policy=policy SocketPermissionTest
  30  * @key intermittent
  31  */
  32 import java.io.IOException;
  33 import java.net.DatagramPacket;
  34 import java.net.DatagramSocket;
  35 import java.net.InetAddress;
  36 import java.net.MulticastSocket;
  37 import java.net.ServerSocket;
  38 import java.net.Socket;
  39 import java.net.SocketPermission;
  40 import java.security.AccessControlContext;
  41 import java.security.AccessController;
  42 import java.security.Permission;
  43 import java.security.Permissions;
  44 import java.security.PrivilegedAction;
  45 import java.security.ProtectionDomain;
  46 import java.util.Arrays;
  47 import java.util.function.Function;
  48 import java.util.function.IntConsumer;
  49 import static jdk.testlibrary.Utils.getFreePort;
  50 import org.testng.annotations.BeforeMethod;
  51 import org.testng.annotations.DataProvider;
  52 import org.testng.annotations.Test;
  53 
  54 public class SocketPermissionTest {
  55     private int freePort = -1;
  56 
  57     //positive tests
  58     @Test(dataProvider = "positiveProvider")
  59     public void testPositive(Function<String, AccessControlContext> genAcc, IntConsumer func) {
  60         String addr = "localhost:" + freePort;
  61         AccessControlContext acc = genAcc.apply(addr);
  62         AccessController.doPrivileged((PrivilegedAction) () -> {
  63             func.accept(freePort);
  64             return null;
  65         }, acc);
  66     }
  67 
  68     //negative tests
  69     @Test(dataProvider = "negativeProvider", expectedExceptions = SecurityException.class)
  70     public void testNegative(AccessControlContext acc, IntConsumer func) {
  71         AccessController.doPrivileged((PrivilegedAction) () -> {
  72             func.accept(freePort);
  73             return null;
  74         }, acc);
  75     }
  76 
  77     @BeforeMethod
  78     public void setFreePort() throws Exception {
  79         freePort = getFreePort();
  80     }
  81 
  82     @DataProvider
  83     public Object[][] positiveProvider() {
  84         //test for SocketPermission "host:port","connect,resolve";
  85         Function<String, AccessControlContext> generateAcc1 = (addr) -> getAccessControlContext(
  86                 new SocketPermission(addr, "listen, connect,resolve"));
  87         IntConsumer func1 = (i) -> connectSocketTest(i);
  88         IntConsumer func2 = (i) -> connectDatagramSocketTest(i);
  89 
  90         //test for SocketPermission "localhost:1024-","accept";
  91         Function<String, AccessControlContext> generateAcc2 = (addr) -> getAccessControlContext(
  92                 new SocketPermission(addr, "listen,connect,resolve"),
  93                 new SocketPermission("localhost:1024-", "accept"));
  94         IntConsumer func3 = (i) -> acceptServerSocketTest(i);
  95 
  96         //test for SocketPermission "229.227.226.221", "connect,accept"
  97         Function<String, AccessControlContext> generateAcc3 = (addr) -> getAccessControlContext(
  98                 new SocketPermission(addr, "listen,resolve"),
  99                 new SocketPermission("229.227.226.221", "connect,accept"));
 100         IntConsumer func4 = (i) -> sendDatagramPacketTest(i);
 101         IntConsumer func5 = (i) -> joinGroupMulticastTest(i);
 102 
 103         //test for SocketPermission "host:port", "listen"
 104         Function<String, AccessControlContext> generateAcc4 = (addr) -> getAccessControlContext(
 105                 new SocketPermission(addr, "listen"));
 106         IntConsumer func6 = (i) -> listenDatagramSocketTest(i);
 107         IntConsumer func7 = (i) -> listenMulticastSocketTest(i);
 108         IntConsumer func8 = (i) -> listenServerSocketTest(i);
 109 
 110         return new Object[][]{
 111             {generateAcc1, func1},
 112             {generateAcc1, func2},
 113             {generateAcc2, func3},
 114             {generateAcc3, func4},
 115             {generateAcc3, func5},
 116             {generateAcc4, func6},
 117             {generateAcc4, func7},
 118             {generateAcc4, func8}
 119         };
 120     }
 121 
 122     @DataProvider
 123     public Object[][] negativeProvider() {
 124         IntConsumer[] funcs = {i -> connectSocketTest(i),
 125             i -> connectDatagramSocketTest(i), i -> acceptServerSocketTest(i),
 126             i -> sendDatagramPacketTest(i), i -> joinGroupMulticastTest(i),
 127             i -> listenDatagramSocketTest(i), i -> listenMulticastSocketTest(i),
 128             i -> listenServerSocketTest(i)};
 129         return Arrays.stream(funcs).map(f -> {
 130             //Construct an AccessControlContext without SocketPermission
 131             AccessControlContext acc = getAccessControlContext(
 132                     new java.io.FilePermission("<<ALL FILES>>", "read,write,execute,delete"),
 133                     new java.net.NetPermission("*"),
 134                     new java.util.PropertyPermission("*", "read,write"),
 135                     new java.lang.reflect.ReflectPermission("*"),
 136                     new java.lang.RuntimePermission("*"),
 137                     new java.security.SecurityPermission("*"),
 138                     new java.io.SerializablePermission("*"));
 139             return new Object[]{acc, f};
 140         }).toArray(Object[][]::new);
 141     }
 142 
 143     public void connectSocketTest(int port) {
 144         try (ServerSocket server = new ServerSocket(port);
 145                 Socket client = new Socket(InetAddress.getLocalHost(), port);) {
 146         } catch (IOException ex) {
 147             throw new RuntimeException(ex);
 148         }
 149     }
 150 
 151     public void connectDatagramSocketTest(int port) {
 152         String msg = "Hello";
 153         try {
 154             InetAddress me = InetAddress.getLocalHost();
 155             try (DatagramSocket ds = new DatagramSocket(port, me)) {
 156                 DatagramPacket dp = new DatagramPacket(msg.getBytes(),
 157                         msg.length(), me, port);
 158                 ds.send(dp);
 159             }
 160         } catch (IOException ex) {
 161             throw new RuntimeException(ex);
 162         }
 163     }
 164 
 165     public void acceptServerSocketTest(int port) {
 166         try {
 167             InetAddress me = InetAddress.getLocalHost();
 168             try (ServerSocket server = new ServerSocket(port)) {
 169                 Socket client = new Socket(me, port);
 170                 server.accept();
 171             }
 172         } catch (IOException ex) {
 173             throw new RuntimeException(ex);
 174         }
 175     }
 176 
 177     public static void sendDatagramPacketTest(int port) {
 178         String msg = "Hello";
 179         try {
 180             InetAddress group = InetAddress.getByName("229.227.226.221");
 181             try (DatagramSocket s = new DatagramSocket(port)) {
 182                 DatagramPacket hi = new DatagramPacket(msg.getBytes(),
 183                         msg.length(), group, port);
 184                 s.send(hi);
 185             }
 186         } catch (IOException ex) {
 187             throw new RuntimeException(ex);
 188         }
 189     }
 190 
 191     public void joinGroupMulticastTest(int port) {
 192         try {
 193             InetAddress group = InetAddress.getByName("229.227.226.221");
 194             try (MulticastSocket s = new MulticastSocket(port)) {
 195                 s.joinGroup(group);
 196                 s.leaveGroup(group);
 197             }
 198         } catch (IOException ex) {
 199             throw new RuntimeException(ex);
 200         }
 201     }
 202 
 203     public void listenDatagramSocketTest(int port) {
 204         try (DatagramSocket ds = new DatagramSocket(port)) {
 205         } catch (IOException ex) {
 206             throw new RuntimeException(ex);
 207         }
 208     }
 209 
 210     public void listenMulticastSocketTest(int port) {
 211         try (MulticastSocket ms = new MulticastSocket(port)) {
 212         } catch (IOException ex) {
 213             throw new RuntimeException(ex);
 214         }
 215     }
 216 
 217     public void listenServerSocketTest(int port) {
 218         try (ServerSocket ms = new ServerSocket(port)) {
 219         } catch (IOException ex) {
 220             throw new RuntimeException(ex);
 221         }
 222     }
 223 
 224     private static AccessControlContext getAccessControlContext(Permission... ps) {
 225         Permissions perms = new Permissions();
 226         for (Permission p : ps) {
 227             perms.add(p);
 228         }
 229         /*
 230          *Create an AccessControlContext that consist a single protection domain
 231          * with only the permissions calculated above
 232          */
 233         ProtectionDomain pd = new ProtectionDomain(null, perms);
 234         return new AccessControlContext(new ProtectionDomain[]{pd});
 235     }
 236 
 237 }