src/jdk.incubator.httpclient/share/classes/jdk/incubator/http/Exchange.java
branchhttp-client-branch
changeset 55764 34d7cc00f87a
parent 55763 634d8e14c172
child 55792 0936888d5a4a
equal deleted inserted replaced
55763:634d8e14c172 55764:34d7cc00f87a
    26 package jdk.incubator.http;
    26 package jdk.incubator.http;
    27 
    27 
    28 import java.io.IOException;
    28 import java.io.IOException;
    29 import java.lang.System.Logger.Level;
    29 import java.lang.System.Logger.Level;
    30 import java.net.InetSocketAddress;
    30 import java.net.InetSocketAddress;
       
    31 import java.net.Proxy;
    31 import java.net.ProxySelector;
    32 import java.net.ProxySelector;
    32 import java.net.SocketPermission;
    33 import java.net.SocketPermission;
    33 import java.net.URI;
    34 import java.net.URI;
    34 import java.net.URISyntaxException;
    35 import java.net.URISyntaxException;
    35 import java.net.URLPermission;
    36 import java.net.URLPermission;
    36 import java.security.AccessControlContext;
    37 import java.security.AccessControlContext;
    37 import java.security.AccessController;
       
    38 import java.security.PrivilegedAction;
       
    39 import java.security.PrivilegedActionException;
       
    40 import java.security.PrivilegedExceptionAction;
       
    41 import java.util.LinkedList;
       
    42 import java.util.List;
    38 import java.util.List;
    43 import java.util.Map;
    39 import java.util.Map;
    44 import java.util.Set;
    40 import java.util.Set;
    45 import java.util.concurrent.CompletableFuture;
    41 import java.util.concurrent.CompletableFuture;
    46 import java.util.concurrent.CompletionException;
       
    47 import java.util.concurrent.Executor;
    42 import java.util.concurrent.Executor;
    48 import jdk.incubator.http.internal.common.MinimalFuture;
    43 import jdk.incubator.http.internal.common.MinimalFuture;
    49 import jdk.incubator.http.internal.common.Utils;
    44 import jdk.incubator.http.internal.common.Utils;
    50 import jdk.incubator.http.internal.common.Log;
    45 import jdk.incubator.http.internal.common.Log;
    51 
    46 
   423 
   418 
   424     /**
   419     /**
   425      * Returns the security permission required for the given details.
   420      * Returns the security permission required for the given details.
   426      * If method is CONNECT, then uri must be of form "scheme://host:port"
   421      * If method is CONNECT, then uri must be of form "scheme://host:port"
   427      */
   422      */
   428     private static URLPermission getPermissionFor(URI uri,
   423     private static URLPermission permissionForServer(URI uri,
   429                                                   String method,
   424                                                     String method,
   430                                                   Map<String, List<String>> headers) {
   425                                                     Map<String, List<String>> headers) {
   431         StringBuilder sb = new StringBuilder();
   426         StringBuilder sb = new StringBuilder();
   432 
   427 
   433         String urlstring, actionstring;
   428         String urlstring, actionstring;
   434 
   429 
   435         if (method.equals("CONNECT")) {
   430         if (method.equals("CONNECT")) {
   459         }
   454         }
   460         return new URLPermission(urlstring, actionstring);
   455         return new URLPermission(urlstring, actionstring);
   461     }
   456     }
   462 
   457 
   463     /**
   458     /**
       
   459      * Returns the security permissions required to connect to the proxy, or
       
   460      * null if none is required or applicable.
       
   461      */
       
   462     static URLPermission permissionForProxy(HttpRequestImpl request) {
       
   463         InetSocketAddress proxyAddress = request.proxy();
       
   464         if (proxyAddress == null)
       
   465             return null;
       
   466 
       
   467         StringBuilder sb = new StringBuilder();
       
   468         sb.append("socket://")
       
   469           .append(proxyAddress.getHostString()).append(":")
       
   470           .append(proxyAddress.getPort());
       
   471         String urlstring = sb.toString();
       
   472         return new URLPermission(urlstring.toString(), "CONNECT");
       
   473     }
       
   474 
       
   475     /**
   464      * Performs the necessary security permission checks required to retrieve
   476      * Performs the necessary security permission checks required to retrieve
   465      * the response. Returns a security exception representing the denied
   477      * the response. Returns a security exception representing the denied
   466      * permission, or null if all checks pass or there is no security manager.
   478      * permission, or null if all checks pass or there is no security manager.
   467      */
   479      */
   468     private SecurityException checkPermissions() {
   480     private SecurityException checkPermissions() {
       
   481         String method = request.method();
   469         SecurityManager sm = System.getSecurityManager();
   482         SecurityManager sm = System.getSecurityManager();
   470         if (sm == null) {
   483         if (sm == null || method.equals("CONNECT")) {
       
   484             // tunneling will have a null acc, which is fine. The proxy
       
   485             // permission check will have already been preformed.
   471             return null;
   486             return null;
   472         }
   487         }
   473 
   488 
   474         String method = request.method();
       
   475         HttpHeaders userHeaders = request.getUserHeaders();
   489         HttpHeaders userHeaders = request.getUserHeaders();
   476         URI u = getURIForSecurityCheck();
   490         URI u = getURIForSecurityCheck();
   477         URLPermission p = getPermissionFor(u, method, userHeaders.map());
   491         URLPermission p = permissionForServer(u, method, userHeaders.map());
   478 
   492 
   479         try {
   493         try {
   480             assert acc != null;
   494             assert acc != null;
   481             sm.checkPermission(p, acc);
   495             sm.checkPermission(p, acc);
   482         } catch (SecurityException e) {
   496         } catch (SecurityException e) {
   483             return e;
   497             return e;
   484         }
   498         }
   485         ProxySelector ps = client.proxy().orElse(null);
   499         ProxySelector ps = client.proxy().orElse(null);
   486         if (ps != null) {
   500         if (ps != null) {
   487             InetSocketAddress proxy = (InetSocketAddress)
       
   488                     ps.select(u).get(0).address(); // TODO: check this
       
   489             // may need additional check
       
   490             if (!method.equals("CONNECT")) {
   501             if (!method.equals("CONNECT")) {
   491                 // a direct http proxy. Need to check access to proxy
   502                 // a non-tunneling HTTP proxy. Need to check access
   492                 try {
   503                 URLPermission proxyPerm = permissionForProxy(request);
   493                     u = new URI("socket", null, proxy.getHostString(),
   504                 if (proxyPerm != null) {
   494                         proxy.getPort(), null, null, null);
   505                     try {
   495                 } catch (URISyntaxException e) {
   506                         sm.checkPermission(proxyPerm, acc);
   496                     throw new InternalError(e); // shouldn't happen
   507                     } catch (SecurityException e) {
   497                 }
   508                         return e;
   498                 p = new URLPermission(u.toString(), "CONNECT");
   509                     }
   499                 try {
       
   500                     sm.checkPermission(p, acc);
       
   501                 } catch (SecurityException e) {
       
   502                     return e;
       
   503                 }
   510                 }
   504             }
   511             }
   505         }
   512         }
   506         return null;
   513         return null;
   507     }
   514     }