diff --git a/src/java.net.http/share/classes/java/net/http/HttpClient.java b/src/java.net.http/share/classes/java/net/http/HttpClient.java index c1269eed823..fbd2e2aba36 100644 --- a/src/java.net.http/share/classes/java/net/http/HttpClient.java +++ b/src/java.net.http/share/classes/java/net/http/HttpClient.java @@ -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; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java index 1ff1e5f4733..71e4e05d2c5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java @@ -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 { @@ -83,8 +64,6 @@ final class Exchange { // used to record possible cancellation raised before the exchImpl // has been established. private volatile IOException failed; - @SuppressWarnings("removal") - final AccessControlContext acc; final MultiExchange multi; final Executor parentExecutor; volatile boolean upgrading; // to HTTP/2 @@ -103,22 +82,6 @@ final class Exchange { 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 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 { } } - CompletableFuture checkCancelled(CompletableFuture cf, HttpConnection connection) { + CompletableFuture checkCancelled(CompletableFuture cf, HttpConnection connection) { return cf.handle((r,t) -> { if (t == null) { if (multi.requestCancelled()) { @@ -354,7 +317,7 @@ final class Exchange { } catch (Throwable x) { if (debug.on()) debug.log("Failed to close connection", x); } - return MinimalFuture.failedFuture(t); + return MinimalFuture.failedFuture(t); } } } @@ -422,15 +385,6 @@ final class Exchange { return responseAsyncImpl(null); } - CompletableFuture 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 { } } - CompletableFuture responseAsyncImpl0(HttpConnection connection) { + CompletableFuture responseAsyncImpl(HttpConnection connection) { Function, CompletableFuture> after407Check; bodyIgnored = null; if (request.expectContinue()) { @@ -735,109 +689,6 @@ final class Exchange { 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> 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(); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientBuilderImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientBuilderImpl.java index c4157b3c74c..65e9210f9cb 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientBuilderImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientBuilderImpl.java @@ -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; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java index e1f4ec16dcd..4d7518d4054 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java @@ -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 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 CompletableFuture> sendAsync(HttpRequest userRequest, BodyHandler 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> mexCf = mex.responseAsync(executor); CompletableFuture> res = mexCf.whenComplete((b,t) -> requestUnreference()); if (DEBUGELAPSED) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java index 839b6a6185d..bb794031508 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java @@ -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 version; private volatile boolean userSetAuthorization; private volatile boolean userSetProxyAuthorization; private static String userAgent() { - PrivilegedAction 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 pa = () -> new InetSocketAddress(host, port); - return AccessController.doPrivileged(pa); + return new InetSocketAddress(host, port); } else { return InetSocketAddress.createUnresolved(host, port); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java index 2c15a704ef9..a7fe5f19e02 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java @@ -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 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 responseHandler; final HttpClientImpl.DelegatingExecutor executor; @@ -155,8 +152,7 @@ class MultiExchange implements Cancelable { HttpRequestImpl requestImpl, HttpClientImpl client, HttpResponse.BodyHandler responseHandler, - PushPromiseHandler pushPromiseHandler, - @SuppressWarnings("removal") AccessControlContext acc) { + PushPromiseHandler pushPromiseHandler) { this.previous = null; this.userRequest = userRequest; this.request = requestImpl; @@ -164,15 +160,11 @@ class MultiExchange 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 implements Cancelable { previousreq = currentreq; currentreq = newrequest; retriedOnce = false; - setExchange(new Exchange<>(currentreq, this, acc)); + setExchange(new Exchange<>(currentreq, this)); return responseAsyncImpl(); }).thenCompose(Function.identity()); } }) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java index 1b42801e9ba..747945701f8 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainHttpConnection.java @@ -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 connectAsync(Exchange exchange) { CompletableFuture 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 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 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()) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java b/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java index 4565514f577..80ca6ba8a3a 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/PlainTunnelingConnection.java @@ -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 mulEx = new MultiExchange<>(null, req, - client, discarding(), null, null); + client, discarding(), null); Exchange connectExchange = mulEx.getExchange(); return connectExchange diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/PrivilegedExecutor.java b/src/java.net.http/share/classes/jdk/internal/net/http/PrivilegedExecutor.java deleted file mode 100644 index 72518f2c4e8..00000000000 --- a/src/java.net.http/share/classes/jdk/internal/net/http/PrivilegedExecutor.java +++ /dev/null @@ -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 pa = () -> { r.run(); return null; }; - AccessController.doPrivileged(pa, acc); - } - } - - @Override - public void execute(Runnable r) { - executor.execute(new PrivilegedRunnable(r, acc)); - } -} diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java index cfb0a20fe94..ecf88eb6566 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/RequestPublishers.java @@ -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. - *

- * 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 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 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 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 inputStreamSupplier) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java index 22e03238d21..79b2332ae37 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java @@ -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{ private final Path file; private final List 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 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 openOptions, - @SuppressWarnings("removal") AccessControlContext acc, - FilePermission filePermission) { + List openOptions) { this.file = file; this.openOptions = openOptions; - this.acc = acc; - this.filePermission = filePermission; } @Override public BodySubscriber 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 { private final Path directory; private final List 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 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 openOptions, - @SuppressWarnings("removal") AccessControlContext acc, - FilePermission... filePermissions) { + List 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); } } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java index 09ad87f9205..04d019e4c81 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java @@ -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 { - - 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 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 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 options, - @SuppressWarnings("removal") AccessControlContext acc, - FilePermission... filePermissions) { + List 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 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 pa = () -> { - Utils.close(out); - return null; - }; - if (isDefaultFS) { - AccessController.doPrivileged(pa, acc, filePermissions); - } else { - AccessController.doPrivileged(pa, acc); - } - } + Utils.close(out); } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java index bb6540e44b9..2a5f125c0c4 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/ImmutableExtendedSSLSession.java @@ -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; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index ef5af764e76..511b17d7813 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -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 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 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 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) () -> - NetProperties.getInteger(name, defaultValue)); + return NetProperties.getInteger(name, defaultValue); } - @SuppressWarnings("removal") public static String getNetProperty(String name) { - return AccessController.doPrivileged((PrivilegedAction) () -> - NetProperties.get(name)); + return NetProperties.get(name); } - @SuppressWarnings("removal") public static boolean getBooleanProperty(String name, boolean def) { - return AccessController.doPrivileged((PrivilegedAction) () -> - 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) () -> - System.getProperty(name)); + return System.getProperty(name); } - @SuppressWarnings("removal") public static int getIntegerProperty(String name, int defaultValue) { - return AccessController.doPrivileged((PrivilegedAction) () -> - 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) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java index abecde71665..d49b8c391cb 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/HPACK.java @@ -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) () -> System.getProperty(PROPERTY)); + String value = System.getProperty(PROPERTY); if (value == null) { LOGGER = new RootLogger(NONE); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java index f88ec774dc0..c1c0853504c 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/websocket/OpeningHandshake.java @@ -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 send() { - PrivilegedAction> 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 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); - } - } } diff --git a/test/jdk/java/net/httpclient/DebugLoggerTest.java b/test/jdk/java/net/httpclient/DebugLoggerTest.java index ec36d62e38e..8d81e5cbe69 100644 --- a/test/jdk/java/net/httpclient/DebugLoggerTest.java +++ b/test/jdk/java/net/httpclient/DebugLoggerTest.java @@ -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() { } } diff --git a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java index 29976edec9a..bafe1496a86 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java +++ b/test/jdk/java/net/httpclient/FilePublisher/FilePublisherPermsTest.java @@ -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"); diff --git a/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java b/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java index 333996496cd..00f532ba47c 100644 --- a/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java +++ b/test/jdk/java/net/httpclient/FilePublisher/SecureZipFSProvider.java @@ -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); } diff --git a/test/jdk/java/net/httpclient/ProxyServer.java b/test/jdk/java/net/httpclient/ProxyServer.java index 7de14a79225..747a20772d1 100644 --- a/test/jdk/java/net/httpclient/ProxyServer.java +++ b/test/jdk/java/net/httpclient/ProxyServer.java @@ -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 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() { - public Void run() { - execute(); - return null; - } - }); - } - } - - public void execute() { int id = 0; try { while (!done) { diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestServerConfigurator.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestServerConfigurator.java index 5d16ac24155..a471f3ce07f 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestServerConfigurator.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/common/TestServerConfigurator.java @@ -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 action = () -> serverAddr.getHostName(); - hostname = AccessController.doPrivileged(action); - } + final String hostname = serverAddr.getHostName(); + final List sniMatchers = List.of(new ServerNameMatcher(hostname)); sslParams.setSNIMatchers(sniMatchers); // configure the server with these custom SSLParameters diff --git a/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java b/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java index 3c857ba1b48..c8920771727 100644 --- a/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java +++ b/test/jdk/java/net/httpclient/security/filePerms/FileProcessorPermissionTest.java @@ -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 SE = SecurityException.class; + + interface ExceptionAction { + T run() throws Exception; + } @Test public void test() throws Exception { - List> list = List.of( + List> 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(); } diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java index 7a960892aec..415caeb1196 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/AuthenticationFilterTest.java @@ -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(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(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(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(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(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(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(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); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java index 6619eff008a..9b5764735b2 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/RawChannelTest.java @@ -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); diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java index 5277eed3ac0..e6897a83de4 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SimpleSSLContext.java @@ -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. - *

- * Using this class with a security manager requires the following - * permissions to be granted: - *

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