You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hc.apache.org by ol...@apache.org on 2019/08/08 15:04:09 UTC
[httpcomponents-core] branch master updated: Execute
Socket[Channel]#connect under doPrivileged
This is an automated email from the ASF dual-hosted git repository.
olegk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/httpcomponents-core.git
The following commit(s) were added to refs/heads/master by this push:
new a652854 Execute Socket[Channel]#connect under doPrivileged
a652854 is described below
commit a652854fb5e63dd8565ed199b48557043277a30d
Author: Simon Willnauer <si...@apache.org>
AuthorDate: Thu Aug 8 15:44:16 2019 +0200
Execute Socket[Channel]#connect under doPrivileged
In order to allow users to run under a security manager that only grants
connect permission to the httpcore codebase the connect methods should
be executed in a doPriveledged block.
This is certainly not the only issue that users run into when they
install a SecurityManager with strict permissions but certainly the
most prominent and most likely one. Upstream components like the client
might also need to protect places accessing the proxy selector etc.
---
.../core5/http/impl/bootstrap/HttpRequester.java | 21 +++++++++++++++++-
.../hc/core5/reactor/SingleCoreIOReactor.java | 25 +++++++++++++++++++++-
2 files changed, 44 insertions(+), 2 deletions(-)
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java
index 492cfe8..11e3c1b 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/http/impl/bootstrap/HttpRequester.java
@@ -33,6 +33,9 @@ import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@@ -82,6 +85,7 @@ import org.apache.hc.core5.pool.ManagedConnPool;
import org.apache.hc.core5.pool.PoolEntry;
import org.apache.hc.core5.pool.PoolStats;
import org.apache.hc.core5.util.Args;
+import org.apache.hc.core5.util.Asserts;
import org.apache.hc.core5.util.TimeValue;
import org.apache.hc.core5.util.Timeout;
@@ -261,7 +265,22 @@ public class HttpRequester implements ConnPoolControl<HttpHost>, ModalCloseable
}
final InetSocketAddress targetAddress = addressResolver.resolve(targetHost);
- sock.connect(targetAddress, socketConfig.getSoTimeout().toMillisIntBound());
+ // Run this under a doPrivileged to support lib users that run under a SecurityManager this allows granting connect permissions
+ // only to this library
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws IOException {
+ sock.connect(targetAddress, socketConfig.getSoTimeout().toMillisIntBound());
+ return null;
+ }
+ });
+ } catch (final PrivilegedActionException e) {
+ Asserts.check(e.getCause() instanceof IOException,
+ "method contract violation only checked exceptions are wrapped: " + e.getCause());
+ // only checked exceptions are wrapped - error and RTExceptions are rethrown by doPrivileged
+ throw (IOException) e.getCause();
+ }
if (URIScheme.HTTPS.same(targetHost.getSchemeName())) {
final SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(
sock, targetHost.getHostName(), targetAddress.getPort(), true);
diff --git a/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java b/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
index 17af207..8b92321 100644
--- a/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
+++ b/httpcore5/src/main/java/org/apache/hc/core5/reactor/SingleCoreIOReactor.java
@@ -36,6 +36,9 @@ import java.nio.channels.CancelledKeyException;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
@@ -48,6 +51,7 @@ import org.apache.hc.core5.function.Decorator;
import org.apache.hc.core5.io.Closer;
import org.apache.hc.core5.net.NamedEndpoint;
import org.apache.hc.core5.util.Args;
+import org.apache.hc.core5.util.Asserts;
import org.apache.hc.core5.util.Timeout;
class SingleCoreIOReactor extends AbstractSingleCoreIOReactor implements ConnectionInitiator {
@@ -322,7 +326,26 @@ class SingleCoreIOReactor extends AbstractSingleCoreIOReactor implements Connect
targetAddress = sessionRequest.remoteAddress;
eventHandlerFactory = this.eventHandlerFactory;
}
- final boolean connected = socketChannel.connect(targetAddress);
+
+ // Run this under a doPrivileged to support lib users that run under a SecurityManager this allows granting connect permissions
+ // only to this library
+ final boolean connected;
+ try {
+ connected = AccessController.doPrivileged(
+ new PrivilegedExceptionAction<Boolean>() {
+ @Override
+ public Boolean run() throws IOException {
+ return socketChannel.connect(targetAddress);
+ };
+ });
+ } catch (final PrivilegedActionException e) {
+ Asserts.check(e.getCause() instanceof IOException,
+ "method contract violation only checked exceptions are wrapped: " + e.getCause());
+ // only checked exceptions are wrapped - error and RTExceptions are rethrown by doPrivileged
+ throw (IOException) e.getCause();
+ }
+
+
final SelectionKey key = socketChannel.register(this.selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
final InternalChannel channel = new InternalConnectChannel(key, socketChannel, sessionRequest, new InternalDataChannelFactory() {