1 /*
   2  * Copyright (c) 2013, 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  * @summary A simple smoke test of the HttpURLPermission mechanism, which checks
  27  *          for either IOException (due to unknown host) or SecurityException
  28  *          due to lack of permission to connect
  29  * @run main/othervm LookupTest
  30  */
  31 
  32 import java.io.BufferedWriter;
  33 import java.io.FilePermission;
  34 import java.io.FileWriter;
  35 import java.io.IOException;
  36 import java.io.InputStream;
  37 import java.io.OutputStream;
  38 import java.io.PrintWriter;
  39 import java.net.NetPermission;
  40 import java.net.ProxySelector;
  41 import java.net.ServerSocket;
  42 import java.net.Socket;
  43 import java.net.SocketPermission;
  44 import java.net.URL;
  45 import java.net.URLConnection;
  46 import java.net.URLPermission;
  47 import java.security.CodeSource;
  48 import java.security.Permission;
  49 import java.security.PermissionCollection;
  50 import java.security.Permissions;
  51 import java.security.Policy;
  52 import java.security.ProtectionDomain;
  53 import static java.nio.charset.StandardCharsets.US_ASCII;
  54 
  55 public class LookupTest {
  56 
  57     static int port;
  58     static volatile ServerSocket serverSocket;
  59 
  60     static void test(String url,
  61                      boolean throwsSecException,
  62                      boolean throwsIOException) {
  63         ProxySelector.setDefault(null);
  64         URL u;
  65         InputStream is = null;
  66         try {
  67             u = new URL(url);
  68             System.err.println("Connecting to " + u);
  69             URLConnection urlc = u.openConnection();
  70             is = urlc.getInputStream();
  71         } catch (SecurityException e) {
  72             if (!throwsSecException) {
  73                 throw new RuntimeException("Unexpected SecurityException:", e);
  74             }
  75             return;
  76         } catch (IOException e) {
  77             if (!throwsIOException) {
  78                 System.err.println("Unexpected IOException:" + e.getMessage());
  79                 throw new RuntimeException(e);
  80             }
  81             return;
  82         } finally {
  83             if (is != null) {
  84                 try {
  85                     is.close();
  86                 } catch (IOException e) {
  87                     System.err.println("Unexpected IOException:" + e.getMessage());
  88                     throw new RuntimeException(e);
  89                 }
  90             }
  91         }
  92 
  93         if (throwsSecException || throwsIOException) {
  94             System.err.printf("was expecting a %s\n", throwsSecException
  95                     ? "security exception" : "IOException");
  96             throw new RuntimeException("was expecting an exception");
  97         }
  98     }
  99 
 100     static final String CWD = System.getProperty("user.dir", ".");
 101 
 102     public static void main(String args[]) throws Exception {
 103         String hostsFileName = CWD + "/LookupTestHosts";
 104         System.setProperty("jdk.net.hosts.file", hostsFileName);
 105         addMappingToHostsFile("allowedAndFound.com",
 106                               "127.0.0.1",
 107                               hostsFileName,
 108                               false);
 109         addMappingToHostsFile("notAllowedButFound.com",
 110                               "99.99.99.99",
 111                               hostsFileName,
 112                               true);
 113         // name "notAllowedAndNotFound.com" is not in map
 114         // name "allowedButNotfound.com" is not in map
 115         Server server = new Server();
 116         try {
 117             Policy.setPolicy(new LookupTestPolicy());
 118             System.setSecurityManager(new SecurityManager());
 119             server.start();
 120             test("http://allowedAndFound.com:"       + port + "/foo", false, false);
 121             test("http://notAllowedButFound.com:"    + port + "/foo", true, false);
 122             test("http://allowedButNotfound.com:"    + port + "/foo", false, true);
 123             test("http://notAllowedAndNotFound.com:" + port + "/foo", true, false);
 124         } finally {
 125             server.terminate();
 126         }
 127     }
 128 
 129     static class Server extends Thread {
 130         private volatile boolean done;
 131 
 132         public Server() throws IOException {
 133             serverSocket = new ServerSocket(0);
 134             port = serverSocket.getLocalPort();
 135         }
 136 
 137         public void run() {
 138             try {
 139                 while (!done) {
 140                     try (Socket s = serverSocket.accept()) {
 141                         readOneRequest(s.getInputStream());
 142                         OutputStream o = s.getOutputStream();
 143                         String rsp = "HTTP/1.1 200 Ok\r\n" +
 144                                      "Connection: close\r\n" +
 145                                      "Content-length: 0\r\n\r\n";
 146                         o.write(rsp.getBytes(US_ASCII));
 147                     }
 148                 }
 149             } catch (IOException e) {
 150                 if (!done)
 151                     e.printStackTrace();
 152             }
 153         }
 154 
 155         void terminate() {
 156             done = true;
 157             try { serverSocket.close(); }
 158             catch (IOException unexpected) { unexpected.printStackTrace(); }
 159         }
 160 
 161         static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' };
 162 
 163         // Read until the end of a HTTP request
 164         void readOneRequest(InputStream is) throws IOException {
 165             int requestEndCount = 0, r;
 166             while ((r = is.read()) != -1) {
 167                 if (r == requestEnd[requestEndCount]) {
 168                     requestEndCount++;
 169                     if (requestEndCount == 4) {
 170                         break;
 171                     }
 172                 } else {
 173                     requestEndCount = 0;
 174                 }
 175             }
 176         }
 177     }
 178 
 179     private static void addMappingToHostsFile(String host,
 180                                               String addr,
 181                                               String hostsFileName,
 182                                               boolean append)
 183         throws IOException
 184     {
 185         String mapping = addr + " " + host;
 186         try (FileWriter fr = new FileWriter(hostsFileName, append);
 187              PrintWriter hfPWriter = new PrintWriter(new BufferedWriter(fr))) {
 188             hfPWriter.println(mapping);
 189         }
 190     }
 191 
 192     static class LookupTestPolicy extends Policy {
 193         final PermissionCollection perms = new Permissions();
 194 
 195         LookupTestPolicy() throws Exception {
 196             perms.add(new NetPermission("setProxySelector"));
 197             perms.add(new SocketPermission("localhost:1024-", "resolve,accept"));
 198             perms.add(new URLPermission("http://allowedAndFound.com:" + port + "/-", "*:*"));
 199             perms.add(new URLPermission("http://allowedButNotfound.com:" + port + "/-", "*:*"));
 200             perms.add(new FilePermission("<<ALL FILES>>", "read,write,delete"));
 201             //perms.add(new PropertyPermission("java.io.tmpdir", "read"));
 202         }
 203 
 204         public PermissionCollection getPermissions(ProtectionDomain domain) {
 205             return perms;
 206         }
 207 
 208         public PermissionCollection getPermissions(CodeSource codesource) {
 209             return perms;
 210         }
 211 
 212         public boolean implies(ProtectionDomain domain, Permission perm) {
 213             return perms.implies(perm);
 214         }
 215     }
 216 }