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/18 09:34:12 UTC

[httpcomponents-client] branch master updated: Execute Socket#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-client.git


The following commit(s) were added to refs/heads/master by this push:
     new 1fc4680  Execute Socket#connect under doPrivileged
1fc4680 is described below

commit 1fc46800d8f4ef26b397054cafaf91da641e98f7
Author: Simon Willnauer <si...@apache.org>
AuthorDate: Sat Aug 17 09:09:38 2019 +0200

    Execute Socket#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.
---
 .../http/socket/PlainConnectionSocketFactory.java   | 21 ++++++++++++++++++++-
 .../http/ssl/SSLConnectionSocketFactory.java        | 21 ++++++++++++++++++++-
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/socket/PlainConnectionSocketFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/socket/PlainConnectionSocketFactory.java
index e5245c6..c828072 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/socket/PlainConnectionSocketFactory.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/socket/PlainConnectionSocketFactory.java
@@ -30,12 +30,16 @@ package org.apache.hc.client5.http.socket;
 import java.io.IOException;
 import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 
 import org.apache.hc.core5.annotation.Contract;
 import org.apache.hc.core5.annotation.ThreadingBehavior;
 import org.apache.hc.core5.http.HttpHost;
 import org.apache.hc.core5.http.protocol.HttpContext;
 import org.apache.hc.core5.io.Closer;
+import org.apache.hc.core5.util.Asserts;
 import org.apache.hc.core5.util.TimeValue;
 
 /**
@@ -74,7 +78,22 @@ public class PlainConnectionSocketFactory implements ConnectionSocketFactory {
             sock.bind(localAddress);
         }
         try {
-            sock.connect(remoteAddress, TimeValue.isPositive(connectTimeout) ? connectTimeout.toMillisIntBound() : 0);
+            // 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(remoteAddress, TimeValue.isPositive(connectTimeout) ? connectTimeout.toMillisIntBound() : 0);
+                        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();
+            }
         } catch (final IOException ex) {
             Closer.closeQuietly(sock);
             throw ex;
diff --git a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java
index fe373c7..741f016 100644
--- a/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java
+++ b/httpclient5/src/main/java/org/apache/hc/client5/http/ssl/SSLConnectionSocketFactory.java
@@ -31,6 +31,9 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
@@ -55,6 +58,7 @@ import org.apache.hc.core5.io.Closer;
 import org.apache.hc.core5.ssl.SSLContexts;
 import org.apache.hc.core5.ssl.SSLInitializationException;
 import org.apache.hc.core5.util.Args;
+import org.apache.hc.core5.util.Asserts;
 import org.apache.hc.core5.util.TimeValue;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -209,7 +213,22 @@ public class SSLConnectionSocketFactory implements LayeredConnectionSocketFactor
             if (this.log.isDebugEnabled()) {
                 this.log.debug("Connecting socket to " + remoteAddress + " with timeout " + connectTimeout);
             }
-            sock.connect(remoteAddress, connectTimeout != null ? connectTimeout.toMillisIntBound() : 0);
+            // 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(remoteAddress, connectTimeout != null ? connectTimeout.toMillisIntBound() : 0);
+                        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();
+            }
         } catch (final IOException ex) {
             Closer.closeQuietly(sock);
             throw ex;