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