8344228: Revisit SecurityManager usage in java.net.http after JEP 486 integration
Reviewed-by: jpai
This commit is contained in:
parent
84ffb64cd7
commit
40a055ebd2
@ -37,9 +37,6 @@ import java.net.CookieHandler;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URLPermission;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.time.Duration;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
@ -26,25 +26,15 @@
|
||||
package jdk.internal.net.http;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ProtocolException;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLPermission;
|
||||
import java.security.AccessControlContext;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.net.http.HttpTimeoutException;
|
||||
|
||||
@ -53,20 +43,11 @@ import jdk.internal.net.http.common.MinimalFuture;
|
||||
import jdk.internal.net.http.common.Utils;
|
||||
import jdk.internal.net.http.common.Log;
|
||||
|
||||
import static jdk.internal.net.http.common.Utils.permissionForProxy;
|
||||
|
||||
/**
|
||||
* One request/response exchange (handles 100/101 intermediate response also).
|
||||
* depth field used to track number of times a new request is being sent
|
||||
* for a given API request. If limit exceeded exception is thrown.
|
||||
*
|
||||
* Security check is performed here:
|
||||
* - uses AccessControlContext captured at API level
|
||||
* - checks for appropriate URLPermission for request
|
||||
* - if permission allowed, grants equivalent SocketPermission to call
|
||||
* - in case of direct HTTP proxy, checks additionally for access to proxy
|
||||
* (CONNECT proxying uses its own Exchange, so check done there)
|
||||
*
|
||||
*/
|
||||
final class Exchange<T> {
|
||||
|
||||
@ -83,8 +64,6 @@ final class Exchange<T> {
|
||||
// used to record possible cancellation raised before the exchImpl
|
||||
// has been established.
|
||||
private volatile IOException failed;
|
||||
@SuppressWarnings("removal")
|
||||
final AccessControlContext acc;
|
||||
final MultiExchange<T> multi;
|
||||
final Executor parentExecutor;
|
||||
volatile boolean upgrading; // to HTTP/2
|
||||
@ -103,22 +82,6 @@ final class Exchange<T> {
|
||||
this.upgrading = false;
|
||||
this.client = multi.client();
|
||||
this.multi = multi;
|
||||
this.acc = multi.acc;
|
||||
this.parentExecutor = multi.executor;
|
||||
this.pushGroup = multi.pushGroup;
|
||||
this.dbgTag = "Exchange";
|
||||
}
|
||||
|
||||
/* If different AccessControlContext to be used */
|
||||
Exchange(HttpRequestImpl request,
|
||||
MultiExchange<T> multi,
|
||||
@SuppressWarnings("removal") AccessControlContext acc)
|
||||
{
|
||||
this.request = request;
|
||||
this.acc = acc;
|
||||
this.upgrading = false;
|
||||
this.client = multi.client();
|
||||
this.multi = multi;
|
||||
this.parentExecutor = multi.executor;
|
||||
this.pushGroup = multi.pushGroup;
|
||||
this.dbgTag = "Exchange";
|
||||
@ -338,7 +301,7 @@ final class Exchange<T> {
|
||||
}
|
||||
}
|
||||
|
||||
<T> CompletableFuture<T> checkCancelled(CompletableFuture<T> cf, HttpConnection connection) {
|
||||
<U> CompletableFuture<U> checkCancelled(CompletableFuture<U> cf, HttpConnection connection) {
|
||||
return cf.handle((r,t) -> {
|
||||
if (t == null) {
|
||||
if (multi.requestCancelled()) {
|
||||
@ -354,7 +317,7 @@ final class Exchange<T> {
|
||||
} catch (Throwable x) {
|
||||
if (debug.on()) debug.log("Failed to close connection", x);
|
||||
}
|
||||
return MinimalFuture.<T>failedFuture(t);
|
||||
return MinimalFuture.<U>failedFuture(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -422,15 +385,6 @@ final class Exchange<T> {
|
||||
return responseAsyncImpl(null);
|
||||
}
|
||||
|
||||
CompletableFuture<Response> responseAsyncImpl(HttpConnection connection) {
|
||||
SecurityException e = checkPermissions();
|
||||
if (e != null) {
|
||||
return MinimalFuture.failedFuture(e);
|
||||
} else {
|
||||
return responseAsyncImpl0(connection);
|
||||
}
|
||||
}
|
||||
|
||||
// check whether the headersSentCF was completed exceptionally with
|
||||
// ProxyAuthorizationRequired. If so the Response embedded in the
|
||||
// exception is returned. Otherwise we proceed.
|
||||
@ -584,7 +538,7 @@ final class Exchange<T> {
|
||||
}
|
||||
}
|
||||
|
||||
CompletableFuture<Response> responseAsyncImpl0(HttpConnection connection) {
|
||||
CompletableFuture<Response> responseAsyncImpl(HttpConnection connection) {
|
||||
Function<ExchangeImpl<T>, CompletableFuture<Response>> after407Check;
|
||||
bodyIgnored = null;
|
||||
if (request.expectContinue()) {
|
||||
@ -735,109 +689,6 @@ final class Exchange<T> {
|
||||
return MinimalFuture.completedFuture(resp);
|
||||
}
|
||||
|
||||
private URI getURIForSecurityCheck() {
|
||||
URI u;
|
||||
String method = request.method();
|
||||
InetSocketAddress authority = request.authority();
|
||||
URI uri = request.uri();
|
||||
|
||||
// CONNECT should be restricted at API level
|
||||
if (method.equalsIgnoreCase("CONNECT")) {
|
||||
try {
|
||||
u = new URI("socket",
|
||||
null,
|
||||
authority.getHostString(),
|
||||
authority.getPort(),
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
} catch (URISyntaxException e) {
|
||||
throw new InternalError(e); // shouldn't happen
|
||||
}
|
||||
} else {
|
||||
u = uri;
|
||||
}
|
||||
return u;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the security permission required for the given details.
|
||||
* If method is CONNECT, then uri must be of form "scheme://host:port"
|
||||
*/
|
||||
private static URLPermission permissionForServer(URI uri,
|
||||
String method,
|
||||
Map<String, List<String>> headers) {
|
||||
if (method.equals("CONNECT")) {
|
||||
return new URLPermission(uri.toString(), "CONNECT");
|
||||
} else {
|
||||
return Utils.permissionForServer(uri, method, headers.keySet().stream());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the necessary security permission checks required to retrieve
|
||||
* the response. Returns a security exception representing the denied
|
||||
* permission, or null if all checks pass or there is no security manager.
|
||||
*/
|
||||
private SecurityException checkPermissions() {
|
||||
String method = request.method();
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null || method.equals("CONNECT")) {
|
||||
// tunneling will have a null acc, which is fine. The proxy
|
||||
// permission check will have already been preformed.
|
||||
return null;
|
||||
}
|
||||
|
||||
HttpHeaders userHeaders = request.getUserHeaders();
|
||||
URI u = getURIForSecurityCheck();
|
||||
URLPermission p = permissionForServer(u, method, userHeaders.map());
|
||||
|
||||
try {
|
||||
assert acc != null;
|
||||
sm.checkPermission(p, acc);
|
||||
} catch (SecurityException e) {
|
||||
return e;
|
||||
}
|
||||
String hostHeader = userHeaders.firstValue("Host").orElse(null);
|
||||
if (hostHeader != null && !hostHeader.equalsIgnoreCase(u.getHost())) {
|
||||
// user has set a Host header different to request URI
|
||||
// must check that for URLPermission also
|
||||
URI u1 = replaceHostInURI(u, hostHeader);
|
||||
URLPermission p1 = permissionForServer(u1, method, userHeaders.map());
|
||||
try {
|
||||
assert acc != null;
|
||||
sm.checkPermission(p1, acc);
|
||||
} catch (SecurityException e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
ProxySelector ps = client.proxySelector();
|
||||
if (ps != null) {
|
||||
if (!method.equals("CONNECT")) {
|
||||
// a non-tunneling HTTP proxy. Need to check access
|
||||
URLPermission proxyPerm = permissionForProxy(request.proxy());
|
||||
if (proxyPerm != null) {
|
||||
try {
|
||||
sm.checkPermission(proxyPerm, acc);
|
||||
} catch (SecurityException e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static URI replaceHostInURI(URI u, String hostPort) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(u.getScheme())
|
||||
.append("://")
|
||||
.append(hostPort)
|
||||
.append(u.getRawPath());
|
||||
return URI.create(sb.toString());
|
||||
}
|
||||
|
||||
HttpClient.Version version() {
|
||||
return multi.version();
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -46,7 +46,6 @@ public class HttpClientBuilderImpl implements HttpClient.Builder {
|
||||
Authenticator authenticator;
|
||||
HttpClient.Version version;
|
||||
Executor executor;
|
||||
// Security parameters
|
||||
SSLContext sslContext;
|
||||
SSLParameters sslParams;
|
||||
int priority = -1;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -48,10 +48,7 @@ import java.nio.channels.ClosedSelectorException;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
@ -97,7 +94,6 @@ import jdk.internal.net.http.common.Utils;
|
||||
import jdk.internal.net.http.common.OperationTrackers.Trackable;
|
||||
import jdk.internal.net.http.common.OperationTrackers.Tracker;
|
||||
import jdk.internal.net.http.websocket.BuilderImpl;
|
||||
import jdk.internal.misc.InnocuousThread;
|
||||
|
||||
/**
|
||||
* Client implementation. Contains all configuration information and also
|
||||
@ -131,16 +127,10 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
namePrefix = "HttpClient-" + clientID + "-Worker-";
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
String name = namePrefix + nextId.getAndIncrement();
|
||||
Thread t;
|
||||
if (System.getSecurityManager() == null) {
|
||||
t = new Thread(null, r, name, 0, false);
|
||||
} else {
|
||||
t = InnocuousThread.newThread(name, r);
|
||||
}
|
||||
Thread t = new Thread(null, r, name, 0, false);
|
||||
t.setDaemon(true);
|
||||
return t;
|
||||
}
|
||||
@ -188,15 +178,9 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void shutdown() {
|
||||
if (delegate instanceof ExecutorService service) {
|
||||
PrivilegedAction<?> action = () -> {
|
||||
service.shutdown();
|
||||
return null;
|
||||
};
|
||||
AccessController.doPrivileged(action, null,
|
||||
new RuntimePermission("modifyThread"));
|
||||
service.shutdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -336,7 +320,6 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
private final ConnectionPool connections;
|
||||
private final DelegatingExecutor delegatingExecutor;
|
||||
private final boolean isDefaultExecutor;
|
||||
// Security parameters
|
||||
private final SSLContext sslContext;
|
||||
private final SSLParameters sslParams;
|
||||
private final SelectorManager selmgr;
|
||||
@ -445,16 +428,6 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
SingleFacadeFactory facadeFactory) {
|
||||
id = CLIENT_IDS.incrementAndGet();
|
||||
dbgTag = "HttpClientImpl(" + id +")";
|
||||
@SuppressWarnings("removal")
|
||||
var sm = System.getSecurityManager();
|
||||
if (sm != null && builder.localAddr != null) {
|
||||
// when a specific local address is configured, it will eventually
|
||||
// lead to the SocketChannel.bind(...) call with an InetSocketAddress
|
||||
// whose InetAddress is the local address and the port is 0. That ultimately
|
||||
// leads to a SecurityManager.checkListen permission check for that port.
|
||||
// so we do that security manager check here with port 0.
|
||||
sm.checkListen(0);
|
||||
}
|
||||
localAddr = builder.localAddr;
|
||||
if (builder.sslContext == null) {
|
||||
try {
|
||||
@ -484,7 +457,7 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
Redirect.NEVER : builder.followRedirects;
|
||||
this.userProxySelector = builder.proxy;
|
||||
this.proxySelector = Optional.ofNullable(userProxySelector)
|
||||
.orElseGet(HttpClientImpl::getDefaultProxySelector);
|
||||
.orElseGet(ProxySelector::getDefault);
|
||||
if (debug.on())
|
||||
debug.log("proxySelector is %s (user-supplied=%s)",
|
||||
this.proxySelector, userProxySelector != null);
|
||||
@ -642,12 +615,6 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
return params;
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static ProxySelector getDefaultProxySelector() {
|
||||
PrivilegedAction<ProxySelector> action = ProxySelector::getDefault;
|
||||
return AccessController.doPrivileged(action);
|
||||
}
|
||||
|
||||
// Returns the facade that was returned to the application code.
|
||||
// May be null if that facade is no longer referenced.
|
||||
final HttpClientFacade facade() {
|
||||
@ -992,7 +959,6 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
return sendAsync(userRequest, responseHandler, pushPromiseHandler, delegatingExecutor.delegate);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private <T> CompletableFuture<HttpResponse<T>>
|
||||
sendAsync(HttpRequest userRequest,
|
||||
BodyHandler<T> responseHandler,
|
||||
@ -1012,11 +978,7 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
return MinimalFuture.failedFuture(selmgr.selectorClosedException());
|
||||
}
|
||||
|
||||
AccessControlContext acc = null;
|
||||
if (System.getSecurityManager() != null)
|
||||
acc = AccessController.getContext();
|
||||
|
||||
// Clone the, possibly untrusted, HttpRequest
|
||||
// Clone the possibly untrusted HttpRequest
|
||||
HttpRequestImpl requestImpl = new HttpRequestImpl(userRequest, proxySelector);
|
||||
if (requestImpl.method().equals("CONNECT"))
|
||||
throw new IllegalArgumentException("Unsupported method CONNECT");
|
||||
@ -1049,8 +1011,7 @@ final class HttpClientImpl extends HttpClient implements Trackable {
|
||||
requestImpl,
|
||||
this,
|
||||
responseHandler,
|
||||
pushPromiseHandler,
|
||||
acc);
|
||||
pushPromiseHandler);
|
||||
CompletableFuture<HttpResponse<T>> mexCf = mex.responseAsync(executor);
|
||||
CompletableFuture<HttpResponse<T>> res = mexCf.whenComplete((b,t) -> requestUnreference());
|
||||
if (DEBUGELAPSED) {
|
||||
|
@ -31,9 +31,6 @@ import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URI;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@ -65,17 +62,13 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
final boolean secure;
|
||||
final boolean expectContinue;
|
||||
private volatile boolean isWebSocket;
|
||||
@SuppressWarnings("removal")
|
||||
private volatile AccessControlContext acc;
|
||||
private final Duration timeout; // may be null
|
||||
private final Optional<HttpClient.Version> version;
|
||||
private volatile boolean userSetAuthorization;
|
||||
private volatile boolean userSetProxyAuthorization;
|
||||
|
||||
private static String userAgent() {
|
||||
PrivilegedAction<String> pa = () -> System.getProperty("java.version");
|
||||
@SuppressWarnings("removal")
|
||||
String version = AccessController.doPrivileged(pa);
|
||||
String version = System.getProperty("java.version");
|
||||
return "Java-http-client/" + version;
|
||||
}
|
||||
|
||||
@ -196,7 +189,6 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
this.expectContinue = other.expectContinue;
|
||||
this.secure = uri.getScheme().toLowerCase(Locale.US).equals("https");
|
||||
this.requestPublisher = mayHaveBody ? publisher(other) : null; // may be null
|
||||
this.acc = other.acc;
|
||||
this.timeout = other.timeout;
|
||||
this.version = other.version();
|
||||
this.authority = null;
|
||||
@ -274,7 +266,6 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
this.expectContinue = parent.expectContinue;
|
||||
this.secure = parent.secure;
|
||||
this.requestPublisher = parent.requestPublisher;
|
||||
this.acc = parent.acc;
|
||||
this.timeout = parent.timeout;
|
||||
this.version = parent.version;
|
||||
this.authority = null;
|
||||
@ -395,7 +386,6 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
systemHeadersBuilder.setHeader(name, value);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
InetSocketAddress getAddress() {
|
||||
URI uri = uri();
|
||||
if (uri == null) {
|
||||
@ -412,8 +402,7 @@ public class HttpRequestImpl extends HttpRequest implements WebSocketRequest {
|
||||
final String host = uri.getHost();
|
||||
final int port = p;
|
||||
if (proxy() == null) {
|
||||
PrivilegedAction<InetSocketAddress> pa = () -> new InetSocketAddress(host, port);
|
||||
return AccessController.doPrivileged(pa);
|
||||
return new InetSocketAddress(host, port);
|
||||
} else {
|
||||
return InetSocketAddress.createUnresolved(host, port);
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ import java.lang.ref.WeakReference;
|
||||
import java.net.ConnectException;
|
||||
import java.net.http.HttpConnectTimeoutException;
|
||||
import java.time.Duration;
|
||||
import java.security.AccessControlContext;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.Objects;
|
||||
@ -79,8 +78,6 @@ class MultiExchange<T> implements Cancelable {
|
||||
private final HttpRequest userRequest; // the user request
|
||||
private final HttpRequestImpl request; // a copy of the user request
|
||||
private final ConnectTimeoutTracker connectTimeout; // null if no timeout
|
||||
@SuppressWarnings("removal")
|
||||
final AccessControlContext acc;
|
||||
final HttpClientImpl client;
|
||||
final HttpResponse.BodyHandler<T> responseHandler;
|
||||
final HttpClientImpl.DelegatingExecutor executor;
|
||||
@ -155,8 +152,7 @@ class MultiExchange<T> implements Cancelable {
|
||||
HttpRequestImpl requestImpl,
|
||||
HttpClientImpl client,
|
||||
HttpResponse.BodyHandler<T> responseHandler,
|
||||
PushPromiseHandler<T> pushPromiseHandler,
|
||||
@SuppressWarnings("removal") AccessControlContext acc) {
|
||||
PushPromiseHandler<T> pushPromiseHandler) {
|
||||
this.previous = null;
|
||||
this.userRequest = userRequest;
|
||||
this.request = requestImpl;
|
||||
@ -164,15 +160,11 @@ class MultiExchange<T> implements Cancelable {
|
||||
this.previousreq = null;
|
||||
this.client = client;
|
||||
this.filters = client.filterChain();
|
||||
this.acc = acc;
|
||||
this.executor = client.theExecutor();
|
||||
this.responseHandler = responseHandler;
|
||||
|
||||
if (pushPromiseHandler != null) {
|
||||
Executor ensureExecutedAsync = this.executor::ensureExecutedAsync;
|
||||
Executor executor = acc == null
|
||||
? ensureExecutedAsync
|
||||
: new PrivilegedExecutor(ensureExecutedAsync, acc);
|
||||
Executor executor = this.executor::ensureExecutedAsync;
|
||||
this.pushGroup = new PushGroup<>(pushPromiseHandler, request, executor);
|
||||
} else {
|
||||
pushGroup = null;
|
||||
@ -470,7 +462,7 @@ class MultiExchange<T> implements Cancelable {
|
||||
previousreq = currentreq;
|
||||
currentreq = newrequest;
|
||||
retriedOnce = false;
|
||||
setExchange(new Exchange<>(currentreq, this, acc));
|
||||
setExchange(new Exchange<>(currentreq, this));
|
||||
return responseAsyncImpl();
|
||||
}).thenCompose(Function.identity());
|
||||
} })
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,9 +32,6 @@ import java.net.StandardSocketOptions;
|
||||
import java.nio.channels.SelectableChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@ -167,7 +164,6 @@ class PlainHttpConnection extends HttpConnection {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
@Override
|
||||
public CompletableFuture<Void> connectAsync(Exchange<?> exchange) {
|
||||
CompletableFuture<ConnectState> cf = new MinimalFuture<>();
|
||||
@ -191,14 +187,12 @@ class PlainHttpConnection extends HttpConnection {
|
||||
debug.log("binding to configured local address " + localAddr);
|
||||
}
|
||||
var sockAddr = new InetSocketAddress(localAddr, 0);
|
||||
PrivilegedExceptionAction<SocketChannel> pa = () -> chan.bind(sockAddr);
|
||||
try {
|
||||
AccessController.doPrivileged(pa);
|
||||
chan.bind(sockAddr);
|
||||
if (debug.on()) {
|
||||
debug.log("bind completed " + localAddr);
|
||||
}
|
||||
} catch (PrivilegedActionException e) {
|
||||
var cause = e.getCause();
|
||||
} catch (IOException cause) {
|
||||
if (debug.on()) {
|
||||
debug.log("bind to " + localAddr + " failed: " + cause.getMessage());
|
||||
}
|
||||
@ -206,13 +200,7 @@ class PlainHttpConnection extends HttpConnection {
|
||||
}
|
||||
}
|
||||
|
||||
PrivilegedExceptionAction<Boolean> pa =
|
||||
() -> chan.connect(Utils.resolveAddress(address));
|
||||
try {
|
||||
finished = AccessController.doPrivileged(pa);
|
||||
} catch (PrivilegedActionException e) {
|
||||
throw e.getCause();
|
||||
}
|
||||
finished = chan.connect(Utils.resolveAddress(address));
|
||||
if (finished) {
|
||||
if (debug.on()) debug.log("connect finished without blocking");
|
||||
if (connectionOpened()) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -72,7 +72,7 @@ final class PlainTunnelingConnection extends HttpConnection {
|
||||
assert client != null;
|
||||
HttpRequestImpl req = new HttpRequestImpl("CONNECT", address, proxyHeaders);
|
||||
MultiExchange<Void> mulEx = new MultiExchange<>(null, req,
|
||||
client, discarding(), null, null);
|
||||
client, discarding(), null);
|
||||
Exchange<Void> connectExchange = mulEx.getExchange();
|
||||
|
||||
return connectExchange
|
||||
|
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.internal.net.http;
|
||||
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
/**
|
||||
* Executes tasks within a given access control context, and by a given executor.
|
||||
*/
|
||||
class PrivilegedExecutor implements Executor {
|
||||
|
||||
/** The underlying executor. May be provided by the user. */
|
||||
final Executor executor;
|
||||
/** The ACC to execute the tasks within. */
|
||||
@SuppressWarnings("removal")
|
||||
final AccessControlContext acc;
|
||||
|
||||
public PrivilegedExecutor(Executor executor, @SuppressWarnings("removal") AccessControlContext acc) {
|
||||
Objects.requireNonNull(executor);
|
||||
Objects.requireNonNull(acc);
|
||||
this.executor = executor;
|
||||
this.acc = acc;
|
||||
}
|
||||
|
||||
private static class PrivilegedRunnable implements Runnable {
|
||||
private final Runnable r;
|
||||
@SuppressWarnings("removal")
|
||||
private final AccessControlContext acc;
|
||||
PrivilegedRunnable(Runnable r, @SuppressWarnings("removal") AccessControlContext acc) {
|
||||
this.r = r;
|
||||
this.acc = acc;
|
||||
}
|
||||
@SuppressWarnings("removal")
|
||||
@Override
|
||||
public void run() {
|
||||
PrivilegedAction<Void> pa = () -> { r.run(); return null; };
|
||||
AccessController.doPrivileged(pa, acc);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Runnable r) {
|
||||
executor.execute(new PrivilegedRunnable(r, acc));
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@ package jdk.internal.net.http;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
@ -37,11 +36,6 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.Permission;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
@ -229,11 +223,6 @@ public final class RequestPublishers {
|
||||
|
||||
/**
|
||||
* Publishes the content of a given file.
|
||||
* <p>
|
||||
* Privileged actions are performed within a limited doPrivileged that only
|
||||
* asserts the specific, read, file permission that was checked during the
|
||||
* construction of this FilePublisher. This only applies if the file system
|
||||
* that created the file provides interoperability with {@code java.io.File}.
|
||||
*/
|
||||
public static class FilePublisher implements BodyPublisher {
|
||||
|
||||
@ -241,62 +230,27 @@ public final class RequestPublishers {
|
||||
private final long length;
|
||||
private final Function<Path, InputStream> inputStreamSupplier;
|
||||
|
||||
private static String pathForSecurityCheck(Path path) {
|
||||
return path.toFile().getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating FilePublisher.
|
||||
*
|
||||
* Permission checks are performed here before construction of the
|
||||
* FilePublisher. Permission checking and construction are deliberately
|
||||
* and tightly co-located.
|
||||
*/
|
||||
public static FilePublisher create(Path path)
|
||||
throws FileNotFoundException {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
FilePermission filePermission = null;
|
||||
boolean defaultFS = true;
|
||||
|
||||
try {
|
||||
String fn = pathForSecurityCheck(path);
|
||||
if (sm != null) {
|
||||
FilePermission readPermission = new FilePermission(fn, "read");
|
||||
sm.checkPermission(readPermission);
|
||||
filePermission = readPermission;
|
||||
}
|
||||
path.toFile().getPath();
|
||||
} catch (UnsupportedOperationException uoe) {
|
||||
// path not associated with the default file system provider
|
||||
defaultFS = false;
|
||||
// Path not associated with the default file system
|
||||
// Test early if an input stream can still be obtained
|
||||
try {
|
||||
if (sm != null) {
|
||||
Files.newInputStream(path).close();
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
if (ioe instanceof FileNotFoundException) {
|
||||
throw (FileNotFoundException) ioe;
|
||||
} else {
|
||||
var ex = new FileNotFoundException(ioe.getMessage());
|
||||
ex.initCause(ioe);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// existence check must be after permission checks
|
||||
// existence check must be after FS checks
|
||||
if (Files.notExists(path))
|
||||
throw new FileNotFoundException(path + " not found");
|
||||
|
||||
Permission perm = filePermission;
|
||||
assert perm == null || perm.getActions().equals("read");
|
||||
@SuppressWarnings("removal")
|
||||
AccessControlContext acc = sm != null ?
|
||||
AccessController.getContext() : null;
|
||||
boolean finalDefaultFS = defaultFS;
|
||||
Function<Path, InputStream> inputStreamSupplier = (p) ->
|
||||
createInputStream(p, acc, perm, finalDefaultFS);
|
||||
createInputStream(p, finalDefaultFS);
|
||||
|
||||
long length;
|
||||
try {
|
||||
@ -308,41 +262,17 @@ public final class RequestPublishers {
|
||||
return new FilePublisher(path, length, inputStreamSupplier);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private static InputStream createInputStream(Path path,
|
||||
AccessControlContext acc,
|
||||
Permission perm,
|
||||
boolean defaultFS) {
|
||||
try {
|
||||
if (acc != null) {
|
||||
PrivilegedExceptionAction<InputStream> pa = defaultFS
|
||||
? () -> new FileInputStream(path.toFile())
|
||||
: () -> Files.newInputStream(path);
|
||||
return perm != null
|
||||
? AccessController.doPrivileged(pa, acc, perm)
|
||||
: AccessController.doPrivileged(pa, acc);
|
||||
} else {
|
||||
return defaultFS
|
||||
return defaultFS
|
||||
? new FileInputStream(path.toFile())
|
||||
: Files.newInputStream(path);
|
||||
}
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw toUncheckedException(pae.getCause());
|
||||
} catch (IOException io) {
|
||||
throw new UncheckedIOException(io);
|
||||
}
|
||||
}
|
||||
|
||||
private static RuntimeException toUncheckedException(Throwable t) {
|
||||
if (t instanceof RuntimeException)
|
||||
throw (RuntimeException) t;
|
||||
if (t instanceof Error)
|
||||
throw (Error) t;
|
||||
if (t instanceof IOException)
|
||||
throw new UncheckedIOException((IOException) t);
|
||||
throw new UndeclaredThrowableException(t);
|
||||
}
|
||||
|
||||
private FilePublisher(Path name,
|
||||
long length,
|
||||
Function<Path, InputStream> inputStreamSupplier) {
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
package jdk.internal.net.http;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.net.URI;
|
||||
@ -34,10 +32,8 @@ import java.nio.file.Files;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.function.Function;
|
||||
@ -56,62 +52,31 @@ public final class ResponseBodyHandlers {
|
||||
|
||||
private ResponseBodyHandlers() { }
|
||||
|
||||
private static final String pathForSecurityCheck(Path path) {
|
||||
return path.toFile().getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* A Path body handler.
|
||||
*/
|
||||
public static class PathBodyHandler implements BodyHandler<Path>{
|
||||
private final Path file;
|
||||
private final List<OpenOption> openOptions; // immutable list
|
||||
@SuppressWarnings("removal")
|
||||
private final AccessControlContext acc;
|
||||
private final FilePermission filePermission;
|
||||
|
||||
/**
|
||||
* Factory for creating PathBodyHandler.
|
||||
*
|
||||
* Permission checks are performed here before construction of the
|
||||
* PathBodyHandler. Permission checking and construction are
|
||||
* deliberately and tightly co-located.
|
||||
*/
|
||||
public static PathBodyHandler create(Path file,
|
||||
List<OpenOption> openOptions) {
|
||||
FilePermission filePermission = null;
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
try {
|
||||
String fn = pathForSecurityCheck(file);
|
||||
FilePermission writePermission = new FilePermission(fn, "write");
|
||||
sm.checkPermission(writePermission);
|
||||
filePermission = writePermission;
|
||||
} catch (UnsupportedOperationException ignored) {
|
||||
// path not associated with the default file system provider
|
||||
}
|
||||
}
|
||||
|
||||
assert filePermission == null || filePermission.getActions().equals("write");
|
||||
@SuppressWarnings("removal")
|
||||
var acc = sm != null ? AccessController.getContext() : null;
|
||||
return new PathBodyHandler(file, openOptions, acc, filePermission);
|
||||
return new PathBodyHandler(file, openOptions);
|
||||
}
|
||||
|
||||
private PathBodyHandler(Path file,
|
||||
List<OpenOption> openOptions,
|
||||
@SuppressWarnings("removal") AccessControlContext acc,
|
||||
FilePermission filePermission) {
|
||||
List<OpenOption> openOptions) {
|
||||
this.file = file;
|
||||
this.openOptions = openOptions;
|
||||
this.acc = acc;
|
||||
this.filePermission = filePermission;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BodySubscriber<Path> apply(ResponseInfo responseInfo) {
|
||||
return new PathSubscriber(file, openOptions, acc, filePermission);
|
||||
return new PathSubscriber(file, openOptions);
|
||||
}
|
||||
}
|
||||
|
||||
@ -170,44 +135,20 @@ public final class ResponseBodyHandlers {
|
||||
public static class FileDownloadBodyHandler implements BodyHandler<Path> {
|
||||
private final Path directory;
|
||||
private final List<OpenOption> openOptions;
|
||||
@SuppressWarnings("removal")
|
||||
private final AccessControlContext acc;
|
||||
private final FilePermission[] filePermissions; // may be null
|
||||
|
||||
/**
|
||||
* Factory for creating FileDownloadBodyHandler.
|
||||
*
|
||||
* Permission checks are performed here before construction of the
|
||||
* FileDownloadBodyHandler. Permission checking and construction are
|
||||
* deliberately and tightly co-located.
|
||||
*/
|
||||
public static FileDownloadBodyHandler create(Path directory,
|
||||
List<OpenOption> openOptions) {
|
||||
String fn;
|
||||
try {
|
||||
fn = pathForSecurityCheck(directory);
|
||||
directory.toFile().getPath();
|
||||
} catch (UnsupportedOperationException uoe) {
|
||||
// directory not associated with the default file system provider
|
||||
throw new IllegalArgumentException("invalid path: " + directory, uoe);
|
||||
}
|
||||
|
||||
FilePermission filePermissions[] = null;
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
FilePermission writePermission = new FilePermission(fn, "write");
|
||||
String writePathPerm = fn + File.separatorChar + "*";
|
||||
FilePermission writeInDirPermission = new FilePermission(writePathPerm, "write");
|
||||
sm.checkPermission(writeInDirPermission);
|
||||
FilePermission readPermission = new FilePermission(fn, "read");
|
||||
sm.checkPermission(readPermission);
|
||||
|
||||
// read permission is only needed before determine the below checks
|
||||
// only write permission is required when downloading to the file
|
||||
filePermissions = new FilePermission[] { writePermission, writeInDirPermission };
|
||||
}
|
||||
|
||||
// existence, etc, checks must be after permission checks
|
||||
// existence, etc, checks must be after FS checks
|
||||
if (Files.notExists(directory))
|
||||
throw new IllegalArgumentException("non-existent directory: " + directory);
|
||||
if (!Files.isDirectory(directory))
|
||||
@ -215,21 +156,13 @@ public final class ResponseBodyHandlers {
|
||||
if (!Files.isWritable(directory))
|
||||
throw new IllegalArgumentException("non-writable directory: " + directory);
|
||||
|
||||
assert filePermissions == null || (filePermissions[0].getActions().equals("write")
|
||||
&& filePermissions[1].getActions().equals("write"));
|
||||
@SuppressWarnings("removal")
|
||||
var acc = sm != null ? AccessController.getContext() : null;
|
||||
return new FileDownloadBodyHandler(directory, openOptions, acc, filePermissions);
|
||||
return new FileDownloadBodyHandler(directory, openOptions);
|
||||
}
|
||||
|
||||
private FileDownloadBodyHandler(Path directory,
|
||||
List<OpenOption> openOptions,
|
||||
@SuppressWarnings("removal") AccessControlContext acc,
|
||||
FilePermission... filePermissions) {
|
||||
List<OpenOption> openOptions) {
|
||||
this.directory = directory;
|
||||
this.openOptions = openOptions;
|
||||
this.acc = acc;
|
||||
this.filePermissions = filePermissions;
|
||||
}
|
||||
|
||||
/** The "attachment" disposition-type and separator. */
|
||||
@ -394,7 +327,7 @@ public final class ResponseBodyHandlers {
|
||||
"Resulting file, " + file.toString() + ", outside of given directory");
|
||||
}
|
||||
|
||||
return new PathSubscriber(file, openOptions, acc, filePermissions);
|
||||
return new PathSubscriber(file, openOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,6 @@
|
||||
package jdk.internal.net.http;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@ -35,11 +34,6 @@ import java.nio.channels.FileChannel;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.OpenOption;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessControlContext;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@ -164,83 +158,31 @@ public class ResponseSubscribers {
|
||||
|
||||
/**
|
||||
* A Subscriber that writes the flow of data to a given file.
|
||||
*
|
||||
* Privileged actions are performed within a limited doPrivileged that only
|
||||
* asserts the specific, write, file permissions that were checked during
|
||||
* the construction of this PathSubscriber.
|
||||
*/
|
||||
public static class PathSubscriber implements TrustedSubscriber<Path> {
|
||||
|
||||
private static final FilePermission[] EMPTY_FILE_PERMISSIONS = new FilePermission[0];
|
||||
|
||||
private final Path file;
|
||||
private final OpenOption[] options;
|
||||
@SuppressWarnings("removal")
|
||||
private final AccessControlContext acc;
|
||||
private final FilePermission[] filePermissions;
|
||||
private final boolean isDefaultFS;
|
||||
private final CompletableFuture<Path> result = new MinimalFuture<>();
|
||||
|
||||
private final AtomicBoolean subscribed = new AtomicBoolean();
|
||||
private volatile Flow.Subscription subscription;
|
||||
private volatile FileChannel out;
|
||||
|
||||
private static final String pathForSecurityCheck(Path path) {
|
||||
return path.toFile().getPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory for creating PathSubscriber.
|
||||
*
|
||||
* Permission checks are performed here before construction of the
|
||||
* PathSubscriber. Permission checking and construction are deliberately
|
||||
* and tightly co-located.
|
||||
*/
|
||||
public static PathSubscriber create(Path file,
|
||||
List<OpenOption> options) {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
FilePermission filePermission = null;
|
||||
if (sm != null) {
|
||||
try {
|
||||
String fn = pathForSecurityCheck(file);
|
||||
FilePermission writePermission = new FilePermission(fn, "write");
|
||||
sm.checkPermission(writePermission);
|
||||
filePermission = writePermission;
|
||||
} catch (UnsupportedOperationException ignored) {
|
||||
// path not associated with the default file system provider
|
||||
}
|
||||
}
|
||||
|
||||
assert filePermission == null || filePermission.getActions().equals("write");
|
||||
@SuppressWarnings("removal")
|
||||
AccessControlContext acc = sm != null ? AccessController.getContext() : null;
|
||||
return new PathSubscriber(file, options, acc, filePermission);
|
||||
return new PathSubscriber(file, options);
|
||||
}
|
||||
|
||||
// pp so handler implementations in the same package can construct
|
||||
/*package-private*/ PathSubscriber(Path file,
|
||||
List<OpenOption> options,
|
||||
@SuppressWarnings("removal") AccessControlContext acc,
|
||||
FilePermission... filePermissions) {
|
||||
List<OpenOption> options) {
|
||||
this.file = file;
|
||||
this.options = options.stream().toArray(OpenOption[]::new);
|
||||
this.acc = acc;
|
||||
this.filePermissions = filePermissions == null || filePermissions[0] == null
|
||||
? EMPTY_FILE_PERMISSIONS : filePermissions;
|
||||
this.isDefaultFS = isDefaultFS(file);
|
||||
}
|
||||
|
||||
private static boolean isDefaultFS(Path file) {
|
||||
try {
|
||||
file.toFile();
|
||||
return true;
|
||||
} catch (UnsupportedOperationException uoe) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
@Override
|
||||
public void onSubscribe(Flow.Subscription subscription) {
|
||||
Objects.requireNonNull(subscription);
|
||||
@ -250,31 +192,12 @@ public class ResponseSubscribers {
|
||||
}
|
||||
|
||||
this.subscription = subscription;
|
||||
if (acc == null) {
|
||||
try {
|
||||
out = FileChannel.open(file, options);
|
||||
} catch (IOException ioe) {
|
||||
result.completeExceptionally(ioe);
|
||||
subscription.cancel();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
PrivilegedExceptionAction<FileChannel> pa =
|
||||
() -> FileChannel.open(file, options);
|
||||
out = isDefaultFS
|
||||
? AccessController.doPrivileged(pa, acc, filePermissions)
|
||||
: AccessController.doPrivileged(pa, acc);
|
||||
} catch (PrivilegedActionException pae) {
|
||||
Throwable t = pae.getCause() != null ? pae.getCause() : pae;
|
||||
result.completeExceptionally(t);
|
||||
subscription.cancel();
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
result.completeExceptionally(e);
|
||||
subscription.cancel();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
out = FileChannel.open(file, options);
|
||||
} catch (IOException ioe) {
|
||||
result.completeExceptionally(ioe);
|
||||
subscription.cancel();
|
||||
return;
|
||||
}
|
||||
subscription.request(1);
|
||||
}
|
||||
@ -311,21 +234,8 @@ public class ResponseSubscribers {
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void close() {
|
||||
if (acc == null) {
|
||||
Utils.close(out);
|
||||
} else {
|
||||
PrivilegedAction<Void> pa = () -> {
|
||||
Utils.close(out);
|
||||
return null;
|
||||
};
|
||||
if (isDefaultFS) {
|
||||
AccessController.doPrivileged(pa, acc, filePermissions);
|
||||
} else {
|
||||
AccessController.doPrivileged(pa, acc);
|
||||
}
|
||||
}
|
||||
Utils.close(out);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -27,7 +27,6 @@ package jdk.internal.net.http.common;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.List;
|
||||
import javax.net.ssl.SSLSession;
|
||||
import javax.net.ssl.ExtendedSSLSession;
|
||||
import javax.net.ssl.SSLSessionContext;
|
||||
import javax.net.ssl.SSLPeerUnverifiedException;
|
||||
|
@ -39,8 +39,6 @@ import java.lang.System.Logger.Level;
|
||||
import java.net.ConnectException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URLPermission;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.net.http.HttpTimeoutException;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -51,8 +49,6 @@ import java.nio.charset.CharacterCodingException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.CodingErrorAction;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.text.Normalizer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@ -100,10 +96,7 @@ public final class Utils {
|
||||
|
||||
// public static final boolean TESTING;
|
||||
// static {
|
||||
// if (ASSERTIONSENABLED) {
|
||||
// PrivilegedAction<String> action = () -> System.getProperty("test.src");
|
||||
// TESTING = AccessController.doPrivileged(action) != null;
|
||||
// } else TESTING = false;
|
||||
// TESTING = ASSERTIONSENABLED ? System.getProperty("test.src") != null : false;
|
||||
// }
|
||||
public static final LoggerConfig DEBUG_CONFIG =
|
||||
getLoggerConfig(DebugLogger.HTTP_NAME, LoggerConfig.OFF);
|
||||
@ -120,9 +113,7 @@ public final class Utils {
|
||||
hostnameVerificationDisabledValue();
|
||||
|
||||
private static LoggerConfig getLoggerConfig(String loggerName, LoggerConfig def) {
|
||||
PrivilegedAction<String> action = () -> System.getProperty(loggerName);
|
||||
@SuppressWarnings("removal")
|
||||
var prop = AccessController.doPrivileged(action);
|
||||
var prop = System.getProperty(loggerName);
|
||||
if (prop == null) return def;
|
||||
var config = LoggerConfig.OFF;
|
||||
for (var s : prop.split(",")) {
|
||||
@ -449,41 +440,6 @@ public final class Utils {
|
||||
|
||||
private Utils() { }
|
||||
|
||||
/**
|
||||
* Returns the security permissions required to connect to the proxy, or
|
||||
* {@code null} if none is required or applicable.
|
||||
*/
|
||||
public static URLPermission permissionForProxy(InetSocketAddress proxyAddress) {
|
||||
if (proxyAddress == null)
|
||||
return null;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("socket://")
|
||||
.append(proxyAddress.getHostString()).append(":")
|
||||
.append(proxyAddress.getPort());
|
||||
String urlString = sb.toString();
|
||||
return new URLPermission(urlString, "CONNECT");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the security permission required for the given details.
|
||||
*/
|
||||
public static URLPermission permissionForServer(URI uri,
|
||||
String method,
|
||||
Stream<String> headers) {
|
||||
String urlString = new StringBuilder()
|
||||
.append(uri.getScheme()).append("://")
|
||||
.append(uri.getRawAuthority())
|
||||
.append(uri.getRawPath()).toString();
|
||||
|
||||
StringBuilder actionStringBuilder = new StringBuilder(method);
|
||||
String collected = headers.collect(joining(","));
|
||||
if (!collected.isEmpty()) {
|
||||
actionStringBuilder.append(":").append(collected);
|
||||
}
|
||||
return new URLPermission(urlString, actionStringBuilder.toString());
|
||||
}
|
||||
|
||||
private static final boolean[] LOWER_CASE_CHARS = new boolean[128];
|
||||
|
||||
// ABNF primitives defined in RFC 7230
|
||||
@ -587,34 +543,24 @@ public final class Utils {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public static int getIntegerNetProperty(String name, int defaultValue) {
|
||||
return AccessController.doPrivileged((PrivilegedAction<Integer>) () ->
|
||||
NetProperties.getInteger(name, defaultValue));
|
||||
return NetProperties.getInteger(name, defaultValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public static String getNetProperty(String name) {
|
||||
return AccessController.doPrivileged((PrivilegedAction<String>) () ->
|
||||
NetProperties.get(name));
|
||||
return NetProperties.get(name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public static boolean getBooleanProperty(String name, boolean def) {
|
||||
return AccessController.doPrivileged((PrivilegedAction<Boolean>) () ->
|
||||
Boolean.parseBoolean(System.getProperty(name, String.valueOf(def))));
|
||||
return Boolean.parseBoolean(System.getProperty(name, String.valueOf(def)));
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public static String getProperty(String name) {
|
||||
return AccessController.doPrivileged((PrivilegedAction<String>) () ->
|
||||
System.getProperty(name));
|
||||
return System.getProperty(name);
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public static int getIntegerProperty(String name, int defaultValue) {
|
||||
return AccessController.doPrivileged((PrivilegedAction<Integer>) () ->
|
||||
Integer.parseInt(System.getProperty(name, String.valueOf(defaultValue))));
|
||||
return Integer.parseInt(System.getProperty(name, String.valueOf(defaultValue)));
|
||||
}
|
||||
|
||||
public static int getIntegerNetProperty(String property, int min, int max, int defaultValue, boolean log) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,8 +28,6 @@ import jdk.internal.net.http.common.Utils;
|
||||
import jdk.internal.net.http.hpack.HPACK.Logger.Level;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.function.Supplier;
|
||||
@ -52,9 +50,7 @@ public final class HPACK {
|
||||
static {
|
||||
String PROPERTY = "jdk.internal.httpclient.hpack.log.level";
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
String value = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty(PROPERTY));
|
||||
String value = System.getProperty(PROPERTY);
|
||||
|
||||
if (value == null) {
|
||||
LOGGER = new RootLogger(NONE);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -39,17 +39,13 @@ import jdk.internal.net.http.common.Pair;
|
||||
import jdk.internal.net.http.common.Utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.net.ProxySelector;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URLPermission;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.security.AccessController;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.SecureRandom;
|
||||
import java.time.Duration;
|
||||
import java.util.Base64;
|
||||
@ -61,11 +57,9 @@ import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static jdk.internal.net.http.common.Utils.isValidName;
|
||||
import static jdk.internal.net.http.common.Utils.permissionForProxy;
|
||||
import static jdk.internal.net.http.common.Utils.stringOf;
|
||||
|
||||
public class OpeningHandshake {
|
||||
@ -112,7 +106,6 @@ public class OpeningHandshake {
|
||||
public OpeningHandshake(BuilderImpl b) {
|
||||
checkURI(b.getUri());
|
||||
Proxy proxy = proxyFor(b.getProxySelector(), b.getUri());
|
||||
checkPermissions(b, proxy);
|
||||
this.client = b.getClient();
|
||||
URI httpURI = createRequestURI(b.getUri());
|
||||
HttpRequestBuilderImpl requestBuilder = new HttpRequestBuilderImpl(httpURI);
|
||||
@ -185,12 +178,9 @@ public class OpeningHandshake {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
public CompletableFuture<Result> send() {
|
||||
PrivilegedAction<CompletableFuture<Result>> pa = () ->
|
||||
client.sendAsync(this.request, BodyHandlers.ofString())
|
||||
return client.sendAsync(this.request, BodyHandlers.ofString())
|
||||
.thenCompose(this::resultFrom);
|
||||
return AccessController.doPrivileged(pa);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -376,27 +366,4 @@ public class OpeningHandshake {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the necessary security permissions checks to connect ( possibly
|
||||
* through a proxy ) to the builders WebSocket URI.
|
||||
*
|
||||
* @throws SecurityException if the security manager denies access
|
||||
*/
|
||||
static void checkPermissions(BuilderImpl b, Proxy proxy) {
|
||||
@SuppressWarnings("removal")
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm == null) {
|
||||
return;
|
||||
}
|
||||
Stream<String> headers = b.getHeaders().stream().map(p -> p.first).distinct();
|
||||
URLPermission perm1 = Utils.permissionForServer(b.getUri(), "", headers);
|
||||
sm.checkPermission(perm1);
|
||||
if (proxy == null) {
|
||||
return;
|
||||
}
|
||||
URLPermission perm2 = permissionForProxy((InetSocketAddress) proxy.address());
|
||||
if (perm2 != null) {
|
||||
sm.checkPermission(perm2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -213,7 +213,7 @@ public class DebugLoggerTest {
|
||||
public void flush() {
|
||||
}
|
||||
@Override
|
||||
public void close() throws SecurityException {
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,6 @@ import org.testng.annotations.Test;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilePermission;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
@ -211,9 +210,6 @@ public class FilePublisherPermsTest implements HttpServerAdapters {
|
||||
|
||||
@BeforeTest
|
||||
public void setup() throws Exception {
|
||||
policyFile = System.getProperty("java.security.policy");
|
||||
out.println(policyFile);
|
||||
|
||||
sslContext = new SimpleSSLContext().get();
|
||||
if (sslContext == null)
|
||||
throw new AssertionError("Unexpected null sslContext");
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -92,13 +92,6 @@ public class SecureZipFSProvider extends FileSystemProvider {
|
||||
public InputStream newInputStream(Path path, OpenOption... options)
|
||||
throws IOException {
|
||||
Path p = toTestPath(path).unwrap();
|
||||
|
||||
// Added permission checks before opening the file
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
if (sm != null) {
|
||||
sm.checkPermission(new RuntimePermission("customPermission"));
|
||||
sm.checkRead(p.toString());
|
||||
}
|
||||
return defaultProvider.newInputStream(p, options);
|
||||
}
|
||||
|
||||
|
@ -27,10 +27,8 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.*;
|
||||
import java.security.*;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.US_ASCII;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static java.nio.charset.StandardCharsets.ISO_8859_1;
|
||||
import static java.util.Arrays.asList;
|
||||
@ -49,9 +47,9 @@ public class ProxyServer extends Thread implements Closeable {
|
||||
// build it. Let's keep it simple.
|
||||
static final boolean IS_WINDOWS;
|
||||
static {
|
||||
PrivilegedAction<String> action =
|
||||
() -> System.getProperty("os.name", "unknown");
|
||||
String osName = AccessController.doPrivileged(action);
|
||||
// Parses os.name directly in order to avoid depending on test
|
||||
// libraries in an auxiliary test class
|
||||
String osName = System.getProperty("os.name", "unknown");
|
||||
IS_WINDOWS = osName.toLowerCase(Locale.ROOT).startsWith("win");
|
||||
}
|
||||
|
||||
@ -151,20 +149,6 @@ public class ProxyServer extends Thread implements Closeable {
|
||||
volatile boolean done;
|
||||
|
||||
public void run() {
|
||||
if (System.getSecurityManager() == null) {
|
||||
execute();
|
||||
} else {
|
||||
// so calling domain does not need to have socket permission
|
||||
AccessController.doPrivileged(new PrivilegedAction<Void>() {
|
||||
public Void run() {
|
||||
execute();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void execute() {
|
||||
int id = 0;
|
||||
try {
|
||||
while (!done) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,8 +23,6 @@
|
||||
package jdk.httpclient.test.lib.common;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.List;
|
||||
|
||||
import javax.net.ssl.SNIMatcher;
|
||||
@ -59,14 +57,8 @@ public final class TestServerConfigurator extends HttpsConfigurator {
|
||||
@Override
|
||||
public void configure(final HttpsParameters params) {
|
||||
final SSLParameters sslParams = getSSLContext().getDefaultSSLParameters();
|
||||
@SuppressWarnings("removal") final SecurityManager sm = System.getSecurityManager();
|
||||
final String hostname;
|
||||
if (sm == null) {
|
||||
hostname = serverAddr.getHostName();
|
||||
} else {
|
||||
final PrivilegedAction<String> action = () -> serverAddr.getHostName();
|
||||
hostname = AccessController.doPrivileged(action);
|
||||
}
|
||||
final String hostname = serverAddr.getHostName();
|
||||
|
||||
final List<SNIMatcher> sniMatchers = List.of(new ServerNameMatcher(hostname));
|
||||
sslParams.setSNIMatchers(sniMatchers);
|
||||
// configure the server with these custom SSLParameters
|
||||
|
@ -29,7 +29,6 @@
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.List;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse.BodyHandlers;
|
||||
@ -43,11 +42,14 @@ public class FileProcessorPermissionTest {
|
||||
static final Path fromFilePath = Paths.get(testSrc, "FileProcessorPermissionTest.java");
|
||||
static final Path asFilePath = Paths.get(testSrc, "asFile.txt");
|
||||
static final Path CWD = Paths.get(".");
|
||||
static final Class<SecurityException> SE = SecurityException.class;
|
||||
|
||||
interface ExceptionAction<T> {
|
||||
T run() throws Exception;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
List<PrivilegedExceptionAction<?>> list = List.of(
|
||||
List<ExceptionAction<?>> list = List.of(
|
||||
() -> HttpRequest.BodyPublishers.ofFile(fromFilePath),
|
||||
|
||||
() -> BodyHandlers.ofFile(asFilePath),
|
||||
@ -59,7 +61,7 @@ public class FileProcessorPermissionTest {
|
||||
() -> BodyHandlers.ofFileDownload(CWD, CREATE, WRITE)
|
||||
);
|
||||
|
||||
for (PrivilegedExceptionAction pa : list) {
|
||||
for (ExceptionAction<?> pa : list) {
|
||||
pa.run();
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -38,7 +38,6 @@ import java.net.URL;
|
||||
import java.net.http.HttpHeaders;
|
||||
import java.net.http.HttpResponse;
|
||||
import java.net.http.HttpResponse.BodyHandlers;
|
||||
import java.security.AccessController;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.Collections;
|
||||
@ -196,8 +195,7 @@ public class AuthenticationFilterTest {
|
||||
HttpRequestImpl origReq = new HttpRequestImpl(reqBuilder);
|
||||
HttpRequestImpl req = new HttpRequestImpl(origReq, ps);
|
||||
MultiExchange<?> multi = new MultiExchange<Void>(origReq, req, client,
|
||||
BodyHandlers.replacing(null),
|
||||
null, AccessController.getContext());
|
||||
BodyHandlers.replacing(null), null);
|
||||
Exchange<?> exchange = new Exchange<>(req, multi);
|
||||
out.println("\nSimulating unauthenticated request to " + uri);
|
||||
filter.request(req, multi);
|
||||
@ -266,8 +264,7 @@ public class AuthenticationFilterTest {
|
||||
HttpRequestImpl origReq2 = new HttpRequestImpl(reqBuilder2);
|
||||
HttpRequestImpl req2 = new HttpRequestImpl(origReq2, ps);
|
||||
MultiExchange<?> multi2 = new MultiExchange<Void>(origReq2, req2, client,
|
||||
HttpResponse.BodyHandlers.replacing(null),
|
||||
null, AccessController.getContext());
|
||||
HttpResponse.BodyHandlers.replacing(null), null);
|
||||
filter.request(req2, multi2);
|
||||
out.println("Check that filter has added credentials from cache for " + reqURI2
|
||||
+ " with proxy " + req2.proxy());
|
||||
@ -298,8 +295,7 @@ public class AuthenticationFilterTest {
|
||||
HttpRequestImpl origReq3 = new HttpRequestImpl(reqBuilder3);
|
||||
HttpRequestImpl req3 = new HttpRequestImpl(origReq3, ps);
|
||||
MultiExchange<?> multi3 = new MultiExchange<Void>(origReq3, req3, client,
|
||||
HttpResponse.BodyHandlers.replacing(null),
|
||||
null, AccessController.getContext());
|
||||
HttpResponse.BodyHandlers.replacing(null), null);
|
||||
filter.request(req3, multi3);
|
||||
HttpHeaders h3 = req3.getSystemHeadersBuilder().build();
|
||||
if (proxy == null) {
|
||||
@ -342,8 +338,7 @@ public class AuthenticationFilterTest {
|
||||
HttpRequestImpl origReq4 = new HttpRequestImpl(reqBuilder4);
|
||||
HttpRequestImpl req4 = new HttpRequestImpl(origReq4, fakeProxy);
|
||||
MultiExchange<?> multi4 = new MultiExchange<Void>(origReq4, req4, client,
|
||||
HttpResponse.BodyHandlers.replacing(null), null,
|
||||
AccessController.getContext());
|
||||
HttpResponse.BodyHandlers.replacing(null), null);
|
||||
out.println("Simulating new request to " + reqURI4 + " with a proxy " + req4.proxy());
|
||||
assertTrue((req4.proxy() == null) == (proxy != null),
|
||||
"(req4.proxy() == null) == (proxy != null) should be true");
|
||||
@ -383,8 +378,7 @@ public class AuthenticationFilterTest {
|
||||
HttpRequestImpl origReq5 = new HttpRequestImpl(reqBuilder5);
|
||||
HttpRequestImpl req5 = new HttpRequestImpl(origReq5, NO_PROXY);
|
||||
MultiExchange<?> multi5 = new MultiExchange<Void>(origReq5, req5, client,
|
||||
HttpResponse.BodyHandlers.replacing(null), null,
|
||||
AccessController.getContext());
|
||||
HttpResponse.BodyHandlers.replacing(null), null);
|
||||
out.println("Simulating new request to " + reqURI + " with a proxy " + req5.proxy());
|
||||
assertTrue(req5.proxy() == null, "req5.proxy() should be null");
|
||||
Exchange<?> exchange5 = new Exchange<>(req5, multi5);
|
||||
@ -437,8 +431,7 @@ public class AuthenticationFilterTest {
|
||||
HttpRequestImpl origReq6 = new HttpRequestImpl(reqBuilder6);
|
||||
HttpRequestImpl req6 = new HttpRequestImpl(origReq6, ps);
|
||||
MultiExchange<?> multi6 = new MultiExchange<Void>(origReq6, req6, client,
|
||||
HttpResponse.BodyHandlers.replacing(null), null,
|
||||
AccessController.getContext());
|
||||
HttpResponse.BodyHandlers.replacing(null), null);
|
||||
out.println("Simulating new request to " + reqURI + " with a proxy " + req6.proxy());
|
||||
assertTrue(req6.proxy() != null, "req6.proxy() should not be null");
|
||||
Exchange<?> exchange6 = new Exchange<>(req6, multi6);
|
||||
@ -461,8 +454,7 @@ public class AuthenticationFilterTest {
|
||||
HttpRequestImpl origReq7 = new HttpRequestImpl(reqBuilder7);
|
||||
HttpRequestImpl req7 = new HttpRequestImpl(origReq7, ps);
|
||||
MultiExchange<?> multi7 = new MultiExchange<Void>(origReq7, req7, client,
|
||||
HttpResponse.BodyHandlers.replacing(null), null,
|
||||
AccessController.getContext());
|
||||
HttpResponse.BodyHandlers.replacing(null), null);
|
||||
out.println("Simulating new request to " + reqURI7 + " with a proxy " + req7.proxy());
|
||||
assertTrue(req7.proxy() == null, "req7.proxy() should be null");
|
||||
Exchange<?> exchange7 = new Exchange<>(req7, multi7);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -221,7 +221,6 @@ public class RawChannelTest {
|
||||
requestImpl,
|
||||
clientImpl,
|
||||
discarding(),
|
||||
null,
|
||||
null);
|
||||
HttpResponse<?> r = mex.responseAsync(clientImpl.theExecutor())
|
||||
.get(30, SECONDS);
|
||||
|
@ -42,13 +42,6 @@ import javax.net.ssl.TrustManagerFactory;
|
||||
/**
|
||||
* Creates a simple usable SSLContext for SSLSocketFactory
|
||||
* or a HttpsServer using a default keystore in the test tree.
|
||||
* <p>
|
||||
* Using this class with a security manager requires the following
|
||||
* permissions to be granted:
|
||||
* <p>
|
||||
* permission "java.util.PropertyPermission" "test.src.path", "read";
|
||||
* permission java.io.FilePermission "/path/to/test/lib/jdk/test/lib/testkeys", "read";
|
||||
* The exact path above depends on the location of the test.
|
||||
*/
|
||||
public class SimpleSSLContext {
|
||||
|
||||
@ -60,27 +53,17 @@ public class SimpleSSLContext {
|
||||
public SimpleSSLContext() throws IOException {
|
||||
String paths = System.getProperty("test.src.path");
|
||||
StringTokenizer st = new StringTokenizer(paths, File.pathSeparator);
|
||||
boolean securityExceptions = false;
|
||||
SSLContext sslContext = null;
|
||||
while (st.hasMoreTokens()) {
|
||||
String path = st.nextToken();
|
||||
try {
|
||||
File f = new File(path, "../../../../../lib/jdk/test/lib/net/testkeys");
|
||||
if (f.exists()) {
|
||||
try (FileInputStream fis = new FileInputStream(f)) {
|
||||
sslContext = init(fis);
|
||||
break;
|
||||
}
|
||||
File f = new File(path, "../../../../../lib/jdk/test/lib/net/testkeys");
|
||||
if (f.exists()) {
|
||||
try (FileInputStream fis = new FileInputStream(f)) {
|
||||
sslContext = init(fis);
|
||||
break;
|
||||
}
|
||||
} catch (SecurityException e) {
|
||||
// catch and ignore because permission only required
|
||||
// for one entry on path (at most)
|
||||
securityExceptions = true;
|
||||
}
|
||||
}
|
||||
if (securityExceptions) {
|
||||
System.out.println("SecurityExceptions thrown on loading testkeys");
|
||||
}
|
||||
ssl = sslContext;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user