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 } |