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