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